/* SovereignScan docs page — follows the sw-* class system used by SwiftLLM. */

const SS_GITHUB_URL = 'https://github.com/Elyeden0/sovereignscan';

const SS_SECTIONS = [
  { id: 'ss-overview',  label: 'Overview' },
  { id: 'ss-pipeline',  label: 'Detection Pipeline' },
  { id: 'ss-risk',      label: 'Risk Engine' },
  { id: 'ss-api',       label: 'API Reference' },
  { id: 'ss-hosting',   label: 'Self-Hosting' },
  { id: 'ss-stack',     label: 'Tech Stack' },
];

function SSCopyBtn({ text }) {
  const t = window.t;
  const [copied, setCopied] = React.useState(false);
  async function onCopy() {
    try {
      await navigator.clipboard.writeText(text);
      setCopied(true);
      setTimeout(() => setCopied(false), 1400);
    } catch (_) {}
  }
  return (
    <button type="button" className="code-copy" onClick={onCopy}>
      {copied ? (
        <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M3 8l4 4 6-8" /></svg>
      ) : (
        <svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><rect x="5" y="5" width="9" height="9" rx="1.5"/><path d="M3 11V3h8"/></svg>
      )}
      <span>{copied ? t('sovereignscan.copied') : t('sovereignscan.copy')}</span>
    </button>
  );
}

function SSCode({ code, lang }) {
  return (
    <div className="code-block">
      <div className="code-block-head">
        <span className="code-block-lang">{lang || 'bash'}</span>
        <SSCopyBtn text={code} />
      </div>
      <pre className="code-block-body"><code>{code}</code></pre>
    </div>
  );
}

function SSSidebar({ activeId }) {
  const t = window.t;
  function onClick(e, id) {
    e.preventDefault();
    const el = document.getElementById(id);
    if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
  }
  return (
    <aside className="sw-sidebar">
      <div className="sw-sidebar-inner">
        <h3 className="sw-sidebar-heading">{t('sovereignscan.sidebarHeading')}</h3>
        <nav className="sw-sidebar-nav">
          {SS_SECTIONS.map(s => (
            <a
              key={s.id}
              href={`#${s.id}`}
              className={`sw-sidebar-item${activeId === s.id ? ' active' : ''}`}
              onClick={e => onClick(e, s.id)}
            >
              <svg width="10" height="10" viewBox="0 0 14 14" fill="none"><path d="M5 3L9 7L5 11" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/></svg>
              <span>{s.label}</span>
            </a>
          ))}
        </nav>
      </div>
    </aside>
  );
}

function SSSection({ id, title, children }) {
  return (
    <section className="sw-doc-section reveal" id={id}>
      <h2 className="sw-doc-title">
        <span className="sw-doc-bracket">&lt;</span>
        <span className="sw-doc-title-text">{title}</span>
        <span className="sw-doc-bracket">{'/>'}</span>
      </h2>
      <div className="sw-doc-body">{children}</div>
    </section>
  );
}

const H3 = ({ children }) => <h3 className="sw-sub">{children}</h3>;
const P  = ({ children }) => <p  className="sw-para">{children}</p>;

function SSBullets({ items }) {
  return (
    <ul className="sw-bullets">
      {items.map((it, i) => (
        <li key={i}>
          <span className="sw-bullet-dot">•</span>
          <span>{it}</span>
        </li>
      ))}
    </ul>
  );
}

function SSGrid({ items }) {
  return (
    <div className="sw-overview-grid">
      {items.map((item, i) => (
        <div className="sw-overview-item" key={i}>
          <span className="sw-overview-num">{String(i + 1).padStart(2, '0')}</span>
          <div className="sw-overview-body">
            <span className="sw-overview-label">{item.label}</span>
            <span className="sw-overview-desc">{item.desc}</span>
          </div>
        </div>
      ))}
    </div>
  );
}

function SovereignScan() {
  window.useLang();
  const t = window.t;
  const [activeId, setActiveId] = React.useState(SS_SECTIONS[0].id);

  React.useEffect(() => {
    const els = SS_SECTIONS.map(s => document.getElementById(s.id)).filter(Boolean);
    const io = new IntersectionObserver(entries => {
      entries.forEach(e => { if (e.isIntersecting) setActiveId(e.target.id); });
    }, { threshold: 0.25 });
    els.forEach(el => io.observe(el));
    return () => io.disconnect();
  }, []);

  return (
    <section className="sw-full-page" id="sovereignscan">
      <div className="container">

        <a href="/docs" className="sw-back">
          <svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M9 12L3 7L9 2" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/></svg>
          <span>{t('sovereignscan.back')}</span>
        </a>

        <div className="sw-full-hero reveal">
          <span className="sw-eyebrow">{t('sovereignscan.eyebrow')}</span>
          <h1 className="sw-full-title">
            <span className="sw-bracket">&lt;</span>
            <span className="sw-title-text">SovereignScan</span>
            <span className="sw-bracket">{'/>'}</span>
          </h1>
          <p className="sw-full-desc">{t('sovereignscan.description')}</p>
          <div className="sw-free-pill">
            <span className="sw-free-text">{t('sovereignscan.openBadge')}</span>
            <span className="sw-free-sep">|</span>
            <span className="sw-free-mit">{t('sovereignscan.mitBadge')}</span>
            <span className="sw-free-sep">|</span>
            <span className="sw-free-text">Python · FastAPI · React</span>
            <span className="sw-free-sep">|</span>
            <a href={SS_GITHUB_URL} target="_blank" rel="noopener noreferrer" className="sw-free-gh">GitHub</a>
          </div>
        </div>

        <div className="sw-doc-grid">
          <SSSidebar activeId={activeId} />

          <div className="sw-doc-content">

            {/* ── Overview ── */}
            <SSSection id="ss-overview" title="Overview">
              <P>
                SovereignScan answers the question a DPO or security reviewer actually has:
                {' '}<em>which governments can legally reach your users' data?</em>
              </P>
              <P>
                Point it at a domain and it crawls every third-party host the page contacts —
                scripts, fonts, pixels, iframes, API endpoints embedded in inline JS —
                then maps each one to a jurisdiction and the laws that apply there.
                It goes further than "data was sent to the US": it names the law, explains what it authorises,
                and factors in whether the vendor's DPA or SCCs change the picture.
              </P>
              <P>
                Your own hosting is always included. If your app runs on a US platform, authorities
                there can compel access to <em>all</em> data on it — not just individual third-party services.
              </P>
              <H3>What makes it different</H3>
              <SSBullets items={[
                'Legal judgment in data, not code — jurisdiction ratings live in sourced JSON files, explainable and contributable.',
                'Conditional ratings — US hosting is High for an unknown vendor but Medium for one offering SCCs + EU residency you can actually configure.',
                'Infrastructure awareness — the scanned domain is always enriched and shown as infrastructure, not buried in the third-party list.',
                'Three-layer provider detection — a custom domain on Vercel, Railway, or Netlify is identified correctly even when the IP resolves to Amazon ASNs.',
              ]} />
            </SSSection>

            {/* ── Detection Pipeline ── */}
            <SSSection id="ss-pipeline" title="Detection Pipeline">
              <P>
                Identifying the real provider behind a hostname is harder than it looks.
                Custom domains give nothing away, PaaS providers lease IP space from cloud giants,
                and apex domains cannot carry a CNAME. SovereignScan resolves this in three layers:
              </P>

              <H3>1 — Suffix / known-domain match</H3>
              <P>
                Every hostname is checked against the vendor database using longest-suffix matching.
                {' '}<code>api.openai.com</code> matches <code>openai.com</code>;
                {' '}<code>my-site.vercel.app</code> matches <code>vercel.app</code>.
                59 vendors covered including major AI, CDN, analytics, hosting, and database providers.
              </P>

              <H3>2 — CNAME chain (custom subdomains)</H3>
              <P>
                When suffix matching fails, the CNAME chain is followed up to five hops
                and the match is retried on the canonical name:
              </P>
              <SSCode lang="dns" code={`blog.acme.com  →  CNAME  →  cname.vercel-dns.com  →  Vercel ✓
shop.acme.com  →  CNAME  →  proxy.mysite.railway.app  →  Railway ✓`} />
              <P>
                Covers any PaaS that uses CNAME delegation: Vercel, Netlify, Railway, Render,
                Fly.io, GitHub Pages, Supabase, and more.
              </P>

              <H3>3 — ASN org name (apex domains &amp; leased IPs)</H3>
              <P>
                Apex domains can't carry a CNAME, so they use an A record directly.
                Many PaaS providers lease IP blocks from cloud giants and register their own org name —
                the ASN number says "Amazon" but the IP belongs to "Vercel, INC."
              </P>
              <SSCode lang="dns" code={`abonnard.dev  →  216.198.79.1  →  AS16509 "Vercel, INC"  →  Vercel ✓
                                 (not AWS, despite the Amazon ASN)`} />
              <P>
                Hosting and database vendors detected via this layer override the raw cloud provider field
                so the host table and infrastructure banner always show the real operator, not the underlying infrastructure.
              </P>
            </SSSection>

            {/* ── Risk Engine ── */}
            <SSSection id="ss-risk" title="Risk Engine">
              <P>
                The engine (<code>api/app/risk/engine.py</code>) is a pure function over a located host.
                Legal signals live in <code>api/app/data/jurisdictions.json</code> — sourced and
                schema-validated in CI.
              </P>
              <SSGrid items={[
                { label: 'Low',     desc: 'Adequate jurisdiction (EU/EEA, UK, CH, JP…) — GDPR adequacy decision in place.' },
                { label: 'Medium',  desc: 'Conditional framework (e.g. US DPF) + SCCs / EU residency / ZDR configured — verify it.' },
                { label: 'High',    desc: 'No adequacy + high state access (US, CN, RU…), or conditional framework with no safeguards found.' },
                { label: 'Unknown', desc: 'Location could not be determined.' },
              ]} />
              <H3>Anycast CDNs</H3>
              <P>
                Cloudflare, Fastly, and similar anycast networks report the nearest PoP, not where data rests.
                For recognised anycast ASNs, risk is assessed against the vendor's <em>primary jurisdiction</em>
                and the report explains the substitution.
              </P>
            </SSSection>

            {/* ── API Reference ── */}
            <SSSection id="ss-api" title="API Reference">
              <P>Interactive docs available at <code>/docs</code> when running locally.</P>
              <SSGrid items={[
                { label: 'POST /api/scan',                desc: 'Scan a URL. Body: { url, extra_hosts? } → ScanReport' },
                { label: 'GET /api/scan/{id}',            desc: 'Fetch a saved report by ID (shareable links)' },
                { label: 'GET /api/scan/{id}/export',     desc: '?format=json|html — download the report' },
                { label: 'GET /api/vendors',              desc: 'The vendor knowledge base (used for autocomplete)' },
                { label: 'GET /api/health',               desc: 'Liveness check' },
              ]} />
              <H3>Scan request</H3>
              <SSCode lang="json" code={`POST /api/scan
Content-Type: application/json

{
  "url": "https://example.com",
  "extra_hosts": ["railway.app", "supabase.com"]
}`} />
              <H3>ScanReport shape</H3>
              <SSCode lang="json" code={`{
  "id": "uuid",
  "url": "https://example.com/",
  "status": "complete" | "partial",
  "durationMs": 1234,
  "hosts": [ThirdPartyHost],
  "recommendations": [Recommendation],
  "chipSovereignty": ChipSovereignty,
  "summary": ScanSummary,
  "warnings": string[]
}`} />
            </SSSection>

            {/* ── Self-Hosting ── */}
            <SSSection id="ss-hosting" title="Self-Hosting">
              <H3>Docker (one command)</H3>
              <SSCode lang="bash" code={`docker compose up --build
# web UI  → http://localhost:8080
# API docs → http://localhost:8000/docs`} />
              <H3>Local dev</H3>
              <SSCode lang="bash" code={`# API
cd api
pip install -r requirements.txt
uvicorn app.main:app --reload   # http://localhost:8000

# Web
cd web
npm install
npm run dev                     # http://localhost:5173`} />
              <P>
                No API keys required. IP enrichment defaults to the keyless <code>ipwho.is</code> provider.
                For higher volume, set <code>SCAN_IP_PROVIDER=ipinfo</code> (token required)
                or <code>maxmind</code> (local GeoLite2 <code>.mmdb</code> files).
              </P>
              <H3>Security</H3>
              <P>
                SSRF defense is first-class: only http/https accepted; private, loopback, link-local,
                CGNAT, and cloud-metadata addresses are refused; the resolved IP is validated (not just
                the hostname); redirects are followed manually and re-checked at every hop.
                Rate-limited per client via <code>SCAN_RATE_LIMIT</code>.
              </P>
            </SSSection>

            {/* ── Stack ── */}
            <SSSection id="ss-stack" title="Tech Stack">
              <H3>Backend</H3>
              <div className="sw-provider-grid">
                {['Python 3.14', 'FastAPI', 'Pydantic v2', 'dnspython', 'httpx', 'aiosqlite', 'slowapi', 'tldextract', 'selectolax'].map(n => (
                  <div className="sw-provider" key={n}><span className="sw-provider-dot" /><span>{n}</span></div>
                ))}
              </div>
              <H3>Frontend</H3>
              <div className="sw-provider-grid">
                {['React 18', 'TypeScript', 'Vite 5', 'Tailwind CSS 4', 'Vitest'].map(n => (
                  <div className="sw-provider" key={n}><span className="sw-provider-dot" /><span>{n}</span></div>
                ))}
              </div>
              <H3>Data</H3>
              <div className="sw-provider-grid">
                {['59 vendors (JSON)', 'Jurisdiction DB', 'ASN → cloud map', 'Chip sovereignty data'].map(n => (
                  <div className="sw-provider" key={n}><span className="sw-provider-dot" /><span>{n}</span></div>
                ))}
              </div>
            </SSSection>

          </div>
        </div>
      </div>
    </section>
  );
}

window.SovereignScan = SovereignScan;
