#nullable enable
using System.Net;
using System.Text;

namespace SelectPdf.Samples
{
    // Wraps a fragment of page content (an .entry-content article, or a
    // statically-rendered sample component) in a COMPLETE, fully-styled
    // SelectPdf.Web design-system HTML document — the SAME full inner-page
    // layout the live Blazor app renders: spdf-nav header + the "All samples"
    // side rail + the content + (optional) the C# code panel + slim footer,
    // styled by assets/css/spdf.css — but emitted as plain static HTML.
    //
    // Why this exists: pages that the SelectPdf converter fetches/renders
    // (the HttpHeaders / HttpCookies / HttpPostRequest echo endpoints and the
    // CurrentWebPageToPdf capture) must NOT be interactive Blazor pages — an
    // InteractiveServer page re-renders over a websocket after the converter's
    // request completes and wipes request-scoped data. But the produced PDF
    // must still look like a real inner page of the sample (full layout, not a
    // bare article). This shell is the single source of truth for that styled
    // document so every converter-target page is consistent and the chrome
    // lives in one place.
    //
    // The nav + side rail + footer markup mirrors
    // Components/Layout/MainLayout.razor (the rail is built from the same
    // SampleCatalog). If that layout changes during the design rollout, update
    // it here too.
    public static class SamplePageShell
    {
        // innerHtml   : the page body (an .entry-content article or rendered component)
        // baseUrl     : scheme+host, e.g. https://localhost:42701 (sets <base>)
        // activeSlug  : rail item to mark aria-current="page" (null = none)
        // codeHtml    : pre-highlighted C# source for the code panel (null = hide panel)
        public static string Wrap(string innerHtml, string baseUrl, string? activeSlug = null, string? codeHtml = null)
        {
            string root = (baseUrl ?? string.Empty).TrimEnd('/');
            int year = System.DateTime.UtcNow.Year;
            // Marketing host for the nav/logo/footer chrome links — selectpdf.net
            // on staging, selectpdf.com on dev/prod (see Program.cs). mktHost is
            // the scheme-less form for the footer's visible host label.
            string mkt = ServerInfo.MarketingBaseUrl;
            string mktHost = ServerInfo.MarketingHost;
            string rail = BuildRail(activeSlug);
            string codePanel = string.IsNullOrEmpty(codeHtml) ? string.Empty : BuildCodePanel(codeHtml!);

            return $$"""
<!DOCTYPE html>
<html lang="en-US" data-palette="amber" data-type="editorial">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="theme-color" content="#FFF8EC">
    <base href="{{root}}/" />

    <link rel="icon" href="favicon.ico" sizes="any">
    <link rel="icon" type="image/png" sizes="32x32" href="icons/icon-32.png">
    <link rel="icon" type="image/png" sizes="16x16" href="icons/icon-16.png">
    <link rel="apple-touch-icon" href="icons/apple-touch-icon.png">

    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Archivo:wght@500;600;700;800&family=Fraunces:ital,opsz,wght@0,9..144,400;0,9..144,500;0,9..144,600;1,9..144,400;1,9..144,500;1,9..144,600&family=IBM+Plex+Mono:wght@400;500;600&family=IBM+Plex+Sans:wght@400;500;600;700&family=Inter:wght@400;500;600;700&family=Inter+Tight:wght@500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">

    <link rel="stylesheet" href="assets/css/spdf.css">

    <style>
        /* PDF-target resets. This document is ONLY ever rendered by the
           SelectPdf converter to a paginated PDF — there is no scrolling
           viewport. Screen affordances (a sticky header, a viewport-height
           scrollable side rail) are laid out against an undefined per-page
           "viewport" in paged media, which scatters the header / content /
           footer onto separate pages with large empty gaps. Flatten them to
           natural top-to-bottom document flow so the PDF is compact.

           NOTE on the side rail specifically: the live pages style it as a
           sticky, `overflow: auto`, ~viewport-tall card. An overflow box is
           atomic (the converter can't break it across pages), so on a SHORT
           page (these header-echo helpers) it can't share page 1 with the nav
           and gets bumped to its own page — reproducing the "blank page 1 +
           footer alone on page 3" split. Flattening it (max-height:none,
           overflow:visible) lets the rail flow with the content so the PDF
           stays content-first and compact. Tall live pages don't need this.
           (Not wrapped in @media print: the Chromium engine renders with
           screen media, so a print block would never apply.) */
        .spdf-nav { position: static !important; }
        .spdf-samples-nav {
            position: static !important;
            top: auto !important;
            max-height: none !important;
            overflow: visible !important;
        }
        /* Paint the root the same cream as <body> so any margin areas between
           blocks don't show through as white bands across page breaks. */
        html { background: var(--spdf-bg); }
    </style>

    <script>
        (function () {
            try {
                var t = localStorage.getItem('spdf-theme');
                if (t === 'dark') document.documentElement.setAttribute('data-theme', 'dark');
            } catch (e) { }
        })();
    </script>
</head>
<body>
<nav class="spdf-nav" x-data="{ drawer: false, menu: null, acc: null }" x-on:keydown.escape="menu = null">
  <div class="spdf-nav-row">
    <div class="spdf-nav-left">
      <a href="{{mkt}}/" class="spdf-nav-logo">
        <svg width="22" height="22" viewBox="0 0 22 22" fill="none" aria-hidden="true">
          <rect x="1" y="1" width="20" height="20" rx="5" stroke="currentColor" stroke-width="1.2"></rect>
          <path d="M6 7 L11 11 L6 15" stroke="var(--spdf-accent)" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" fill="none"></path>
          <line x1="12.5" y1="15" x2="16" y2="15" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"></line>
        </svg>
        <span>select<span class="spdf-nav-logo-accent">pdf</span></span>
      </a>
      <div class="spdf-nav-links">
        <div class="spdf-nav-item" x-on:mouseenter="menu='products'" x-on:mouseleave="menu=null">
          <button type="button" class="spdf-nav-trigger" :aria-expanded="(menu==='products').toString()" x-on:click="menu = menu==='products' ? null : 'products'">Products <span class="spdf-nav-caret" aria-hidden="true">▾</span></button>
          <div class="spdf-nav-menu" x-show="menu==='products'" x-cloak>
            <a href="{{mkt}}/html-to-pdf-online/" class="spdf-nav-menu-link">Create PDF Online<small>Free online HTML / URL → PDF</small></a>
            <a href="{{mkt}}/pdf-library-for-net/" class="spdf-nav-menu-link">.NET Library<small>Commercial · self-hosted</small></a>
            <a href="{{mkt}}/html-to-pdf-converter-for-net/" class="spdf-nav-menu-link">HTML→PDF Converter for .NET<small>Commercial</small></a>
            <a href="{{mkt}}/community-edition/" class="spdf-nav-menu-link">Community Edition<small>Free .NET converter</small></a>
          </div>
        </div>
        <div class="spdf-nav-item" x-on:mouseenter="menu='api'" x-on:mouseleave="menu=null">
          <button type="button" class="spdf-nav-trigger" :aria-expanded="(menu==='api').toString()" x-on:click="menu = menu==='api' ? null : 'api'">API <span class="spdf-nav-caret" aria-hidden="true">▾</span></button>
          <div class="spdf-nav-menu" x-show="menu==='api'" x-cloak>
            <a href="{{mkt}}/html-to-pdf-api/" class="spdf-nav-menu-link">HTML→PDF API<small>REST · any language</small></a>
            <a href="{{mkt}}/html-to-pdf-api-parameters/" class="spdf-nav-menu-link">HTML→PDF API Parameters<small>Full reference · 90 params</small></a>
            <a href="{{mkt}}/pdf-to-text-api/" class="spdf-nav-menu-link">PDF→Text API<small>Extract text or search PDFs · 14 params</small></a>
            <a href="{{mkt}}/pdf-merge-api/" class="spdf-nav-menu-link">PDF Merge API<small>Combine local + remote PDFs · 25 params</small></a>
            <a href="{{mkt}}/save-as-pdf-link/" class="spdf-nav-menu-link">Save as PDF Link<small>Browser button</small></a>
          </div>
        </div>
        <div class="spdf-nav-item" x-on:mouseenter="menu='pricing'" x-on:mouseleave="menu=null">
          <button type="button" class="spdf-nav-trigger" :aria-expanded="(menu==='pricing').toString()" x-on:click="menu = menu==='pricing' ? null : 'pricing'">Pricing <span class="spdf-nav-caret" aria-hidden="true">▾</span></button>
          <div class="spdf-nav-menu" x-show="menu==='pricing'" x-cloak>
            <span class="spdf-nav-menu-group">.NET Library</span>
            <a href="{{mkt}}/pricing/" class="spdf-nav-menu-link is-featured">.NET Library Pricing<small>New perpetual licenses</small></a>
            <a href="{{mkt}}/pricing-3-years-maintenance-plan/" class="spdf-nav-menu-link">3-Year Maintenance Plan</a>
            <a href="{{mkt}}/pricing-5-years-maintenance-plan/" class="spdf-nav-menu-link">5-Year Maintenance Plan</a>
            <a href="{{mkt}}/pricing-renewal/" class="spdf-nav-menu-link">Renewal — Valid Maintenance</a>
            <a href="{{mkt}}/pricing-renewal-late/" class="spdf-nav-menu-link">Renewal — Expired Maintenance</a>
            <a href="{{mkt}}/pricing-renewal-3-years/" class="spdf-nav-menu-link">3-Year Renewal</a>
            <span class="spdf-nav-menu-group">Online API</span>
            <a href="{{mkt}}/api-pricing/" class="spdf-nav-menu-link is-featured">Online API Pricing<small>Metered monthly plans</small></a>
          </div>
        </div>
        <div class="spdf-nav-item" x-on:mouseenter="menu='resources'" x-on:mouseleave="menu=null">
          <button type="button" class="spdf-nav-trigger" :aria-expanded="(menu==='resources').toString()" x-on:click="menu = menu==='resources' ? null : 'resources'">Resources <span class="spdf-nav-caret" aria-hidden="true">▾</span></button>
          <div class="spdf-nav-menu" x-show="menu==='resources'" x-cloak>
            <span class="spdf-nav-menu-group">Commercial Library</span>
            <a href="{{mkt}}/pdf-library/" class="spdf-nav-menu-link">Online Documentation</a>
            <a href="{{mkt}}/demo/" class="spdf-nav-menu-link">Live Demo — ASP.NET (C#)</a>
            <a href="{{mkt}}/demo-vb/" class="spdf-nav-menu-link">Live Demo — ASP.NET (VB.NET)</a>
            <a href="{{mkt}}/demo-mvc/" class="spdf-nav-menu-link">Live Demo — ASP.NET MVC (C#)</a>
            <a href="{{mkt}}/demo-mvc-vb/" class="spdf-nav-menu-link">Live Demo — ASP.NET MVC (VB.NET)</a>
            <a href="{{mkt}}/downloads/" class="spdf-nav-menu-link">Download — Library trial</a>
            <span class="spdf-nav-menu-group">Community Edition · free</span>
            <a href="{{mkt}}/html-to-pdf/docs/" class="spdf-nav-menu-link">Online Documentation</a>
            <a href="{{mkt}}/html-to-pdf/demo/" class="spdf-nav-menu-link">Live Demo — C#</a>
            <a href="{{mkt}}/html-to-pdf/demo-vb/" class="spdf-nav-menu-link">Live Demo — VB.NET</a>
            <a href="{{mkt}}/community-edition/" class="spdf-nav-menu-link">Community Edition</a>
            <a href="{{mkt}}/free-downloads/" class="spdf-nav-menu-link">Free Download</a>
            <span class="spdf-nav-menu-group">General</span>
            <a href="{{mkt}}/blog/" class="spdf-nav-menu-link">Blog</a>
          </div>
        </div>
        <div class="spdf-nav-item" x-on:mouseenter="menu='company'" x-on:mouseleave="menu=null">
          <button type="button" class="spdf-nav-trigger" :aria-expanded="(menu==='company').toString()" x-on:click="menu = menu==='company' ? null : 'company'">Company <span class="spdf-nav-caret" aria-hidden="true">▾</span></button>
          <div class="spdf-nav-menu is-right" x-show="menu==='company'" x-cloak>
            <a href="{{mkt}}/about/" class="spdf-nav-menu-link">About</a>
            <a href="{{mkt}}/contact/" class="spdf-nav-menu-link">Contact</a>
            <a href="{{mkt}}/privacy-policy/" class="spdf-nav-menu-link">Privacy Policy</a>
            <a href="{{mkt}}/terms-and-conditions/" class="spdf-nav-menu-link">Terms &amp; Conditions</a>
            <a href="{{mkt}}/refunds-policy/" class="spdf-nav-menu-link">Refunds Policy</a>
          </div>
        </div>
      </div>
    </div>

    <div class="spdf-nav-actions">
      <button class="spdf-theme-toggle"
              type="button"
              x-on:click="$store.spdf.toggleTheme()"
              :aria-label="$store.spdf.theme === 'dark' ? 'Switch to light mode' : 'Switch to dark mode'"
              title="Toggle dark mode">
        <svg class="icon-moon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
          <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
        </svg>
        <svg class="icon-sun" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
          <circle cx="12" cy="12" r="4"></circle>
          <path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"></path>
        </svg>
      </button>
      <a class="spdf-nav-signin" href="#">Sign in</a>
      <a class="spdf-nav-cta" href="{{mkt}}/pricing/" title="SelectPdf .NET Library pricing — perpetual licenses" aria-label="SelectPdf .NET Library pricing">Buy .NET library →</a>
    </div>
  </div>
</nav>

<main>
  <div class="spdf-shell spdf-pad spdf-samples-main">
    <div class="spdf-samples-layout">
      {{rail}}
      <div class="spdf-samples-content">
        {{innerHtml}}
        {{codePanel}}
      </div>
    </div>
  </div>
</main>

<footer>
  <div class="spdf-footer-meta">
    <span>© SELECTPDF <span data-spdf-year>{{year}}</span> · SelectPdf for .NET 10 — sample code</span>
    <span>
      <a class="spdf-footer-link" href="{{mkt}}" style="display:inline;">{{mktHost}}</a> ·
      <a class="spdf-footer-link" href="{{mkt}}/contact" style="display:inline;">Contact</a> ·
      <a class="spdf-footer-link" href="{{mkt}}/pdf-library-for-net/" style="display:inline;">PDF Library for .NET</a>
    </span>
  </div>
</footer>

<script defer src="assets/js/spdf.js"></script>
<script defer src="assets/js/alpine.3.14.1.min.js"></script>
</body>
</html>
""";
        }

        // Builds the "All samples" side rail from SampleCatalog — the same
        // markup MainLayout.razor renders for an inner page.
        private static string BuildRail(string? activeSlug)
        {
            var sb = new StringBuilder();
            sb.Append("""
<aside class="spdf-samples-nav" x-data="{ railOpen: false }" :data-rail-open="railOpen.toString()">
  <button type="button" class="spdf-samples-nav-toggle" x-on:click="railOpen = !railOpen" :aria-expanded="railOpen.toString()">
    All samples <span class="spdf-nav-caret" aria-hidden="true">▾</span>
  </button>
  <div class="spdf-samples-nav-list">
    <a href="." class="spdf-samples-nav-home">
      <span class="spdf-samples-nav-home-icon" aria-hidden="true">
        <svg width="14" height="14" viewBox="0 0 16 16" fill="none">
          <rect x="1.5" y="1.5" width="5" height="5" rx="1.2" stroke="currentColor" stroke-width="1.3"></rect>
          <rect x="9.5" y="1.5" width="5" height="5" rx="1.2" stroke="currentColor" stroke-width="1.3"></rect>
          <rect x="1.5" y="9.5" width="5" height="5" rx="1.2" stroke="currentColor" stroke-width="1.3"></rect>
          <rect x="9.5" y="9.5" width="5" height="5" rx="1.2" stroke="currentColor" stroke-width="1.3"></rect>
        </svg>
      </span>
      Samples home
    </a>
""");
            foreach (var group in SampleCatalog.Groups)
            {
                sb.Append("    <div class=\"spdf-samples-nav-group\">")
                  .Append(WebUtility.HtmlEncode(group.Name))
                  .Append("</div>\n");
                foreach (var item in group.Items)
                {
                    bool active = string.Equals(item.Slug, activeSlug, System.StringComparison.OrdinalIgnoreCase);
                    sb.Append("    <a href=\"").Append(item.Slug).Append('"');
                    if (active) sb.Append(" aria-current=\"page\"");
                    sb.Append('>').Append(WebUtility.HtmlEncode(item.Title)).Append("</a>\n");
                }
            }
            sb.Append("  </div>\n</aside>");
            return sb.ToString();
        }

        // Builds the C# code panel — same markup MainLayout.razor renders
        // below an inner page's content.
        private static string BuildCodePanel(string codeHtml) => $$"""
<div class="spdf-code spdf-code-block">
  <div class="spdf-code-head">
    <span class="spdf-code-dots"><span class="spdf-code-dot-red"></span><span class="spdf-code-dot-yellow"></span><span class="spdf-code-dot-green"></span></span>
    <span>Sample code · C#</span>
  </div>
  <div class="spdf-code-pre">{{codeHtml}}</div>
</div>
""";
    }
}
