<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <meta name="theme-color" content="#0EA5E9" />
  <title>Finding viewer · takedowns</title>
  <link rel="stylesheet" href="/public/css/glass.css?v=2-light" />
  <style>
    /* Layout: header | toolbar | viewer */
    body { background: var(--bg, #0c0e14); color: var(--fg, #e6e8ee); }
    .viewer-shell { display: flex; flex-direction: column; height: 100vh; }
    .toolbar { display: flex; align-items: center; gap: .5rem; padding: .6rem 1rem; border-bottom: 1px solid var(--line, #2a2f3a); background: var(--bg-2, #11141c); }
    .toolbar .url { flex: 1; min-width: 0; font-family: var(--mono); font-size: .85rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; opacity: .85; }
    .toolbar input[type=search] { padding: .35rem .6rem; min-width: 220px; background: var(--bg-3, #1a1f2a); color: inherit; border: 1px solid var(--line, #2a2f3a); border-radius: 4px; }
    .toolbar .pill { font-size: .7rem; padding: .1rem .45rem; border-radius: 999px; border: 1px solid var(--line); opacity: .85; }
    .toolbar .pill.ok    { background: rgba(80, 200, 120, .12); border-color: rgba(80, 200, 120, .5); }
    .toolbar .pill.warn  { background: rgba(240, 180, 60, .12); border-color: rgba(240, 180, 60, .5); }
    .toolbar .pill.bad   { background: rgba(230, 80, 80, .12); border-color: rgba(230, 80, 80, .5); }
    .toolbar .pill.video { background: rgba(150, 90, 220, .12); border-color: rgba(150, 90, 220, .5); }
    .toolbar .pill.image { background: rgba(220, 100, 150, .12); border-color: rgba(220, 100, 150, .5); }
    .toolbar .pill.other { background: rgba(120, 130, 200, .12); border-color: rgba(120, 130, 200, .5); }
    .toolbar .pill.name  { background: rgba(120, 160, 200, .12); border-color: rgba(120, 160, 200, .5); }
    .toolbar .pill.unknown { background: rgba(160, 160, 160, .12); border-color: rgba(160, 160, 160, .5); }
    .toolbar button { padding: .35rem .75rem; background: var(--bg-3, #1a1f2a); color: inherit; border: 1px solid var(--line, #2a2f3a); border-radius: 4px; cursor: pointer; font-size: .85rem; }
    .toolbar button:hover { background: var(--bg-2, #11141c); border-color: var(--accent, #4f8cff); }
    .toolbar button.primary { background: var(--accent, #4f8cff); color: #fff; border-color: var(--accent, #4f8cff); }
    .toolbar button.primary:hover { filter: brightness(1.1); }
    .toolbar button:disabled { opacity: .5; cursor: not-allowed; }

    .evidence-pane { padding: .6rem 1rem; border-bottom: 1px solid var(--line, #2a2f3a); background: var(--bg-2, #11141c); display: none; }
    .evidence-pane.show { display: block; }
    .evidence-pane .row { font-size: .85rem; margin: .25rem 0; }
    .evidence-pane .label { opacity: .65; margin-right: .35rem; }
    .evidence-pane .evidence-quote { font-style: italic; color: var(--accent, #4f8cff); }

    .viewer-frame { flex: 1; border: 0; background: #fff; }
    .upgrade-banner { padding: 1.5rem; text-align: center; }
    .upgrade-banner h2 { margin: 0 0 .5rem 0; }
    .upgrade-banner a.button { display: inline-block; margin-top: 1rem; padding: .6rem 1.2rem; background: var(--accent, #4f8cff); color: #fff; border-radius: 4px; text-decoration: none; }

    /* In-page search highlight (overlay) */
    .in-page-search { position: fixed; bottom: 1rem; right: 1rem; background: var(--bg-2, #11141c); border: 1px solid var(--line); padding: .5rem; border-radius: 6px; display: none; z-index: 9999; }
    .in-page-search.show { display: flex; gap: .4rem; align-items: center; }
    .in-page-search input { background: var(--bg-3, #1a1f2a); color: inherit; border: 1px solid var(--line); padding: .3rem .5rem; min-width: 200px; }
    .in-page-search button { padding: .3rem .6rem; background: var(--accent); color: #fff; border: 0; border-radius: 4px; cursor: pointer; }
  </style>
</head>
<body>
  <div class="viewer-shell">
    <div class="toolbar">
      <a href="/cases/?id=CASE_ID" class="pill">← back to case</a>
      <span class="url" id="url">loading…</span>
      <span id="categoryPill" class="pill" style="display:none">…</span>
      <span id="tierPill" class="pill">T?</span>
      <span id="statusPill" class="pill">…</span>
      <input type="search" id="crossSearch" placeholder="Search across all findings on this case…" />
      <button id="openSearchBtn" title="Search this page (Ctrl+F)">🔍 Page</button>
      <button id="classifyBtn" title="Run AI categorization (one call)">⚙ Classify</button>
      <button id="saveBtn" class="primary" title="Download a self-contained MHTML file">⬇ Save .mhtml</button>
    </div>

    <div class="evidence-pane" id="evidencePane">
      <div class="row"><span class="label">Category:</span> <span id="evCategory">—</span></div>
      <div class="row"><span class="label">Confidence:</span> <span id="evConfidence">—</span></div>
      <div class="row"><span class="label">Evidence:</span> <span id="evEvidence" class="evidence-quote">—</span></div>
      <div class="row"><span class="label">Summary:</span> <span id="evSummary">—</span></div>
      <div class="row muted" style="opacity:.6"><span class="label">Model:</span> <span id="evModel">—</span> · <span id="evTriggered">—</span> · <span id="evAt">—</span></div>
    </div>

    <iframe class="viewer-frame" id="frame" sandbox="allow-same-origin"></iframe>

    <div class="in-page-search" id="inPageSearch">
      <input type="search" id="inPageQuery" placeholder="Find in this page…" />
      <button id="inPageNext">Next</button>
      <button id="inPageClose">×</button>
    </div>
  </div>

  <script>
    // ---- config from URL ----
    const params = new URLSearchParams(location.search);
    const FINDING_ID = parseInt(params.get('id') || location.pathname.split('/').filter(Boolean).pop() || '0', 10);
    const CASE_ID    = parseInt(params.get('case_id') || '0', 10);
    const csrf = (() => {
      const m = document.cookie.match(/(?:^|;\s*)ncsrf=([^;]+)/);
      return m ? m[1] : '';
    })();

    const el = (id) => document.getElementById(id);
    const pillForCategory = {
      unauthorized_video: { cls: 'video', label: 'unauthorized video' },
      unauthorized_image: { cls: 'image', label: 'unauthorized image' },
      unauthorized_other: { cls: 'other', label: 'unauthorized (other)' },
      name_only:          { cls: 'name',  label: 'name only — not NCII' },
      not_ncii:           { cls: 'ok',    label: 'not NCII' },
      unknown:            { cls: 'unknown', label: 'unknown' },
    };
    const pillForStatus = {
      pending:         { cls: '',     label: 'pending' },
      confirmed:       { cls: 'ok',   label: 'confirmed' },
      dismissed:       { cls: 'bad',  label: 'dismissed' },
      takedown_queued: { cls: 'warn', label: 'takedown queued' },
      takedown_sent:   { cls: 'warn', label: 'takedown sent' },
      removed:         { cls: 'ok',   label: 'removed' },
    };
    function applyCategory(c) {
      const pill = el('categoryPill');
      if (!c) { pill.style.display = 'none'; return; }
      const meta = pillForCategory[c.category] || { cls: 'unknown', label: c.category };
      pill.className = 'pill ' + meta.cls;
      pill.textContent = meta.label + ' (' + Math.round((c.confidence||0)*100) + '%)';
      pill.title = (c.evidence ? 'evidence: ' + c.evidence + '\n' : '') + (c.summary || '');
      pill.style.display = '';
      // show evidence pane
      el('evidencePane').classList.add('show');
      el('evCategory').textContent   = meta.label;
      el('evConfidence').textContent = Math.round((c.confidence||0)*100) + '%';
      el('evEvidence').textContent   = c.evidence   || '—';
      el('evSummary').textContent    = c.summary    || '—';
      el('evModel').textContent      = c.model      || '—';
      el('evTriggered').textContent  = c.triggered_by || '—';
      el('evAt').textContent         = c.classified_at ? new Date(c.classified_at).toLocaleString() : '—';
    }

    async function api(path, opts = {}) {
      const r = await fetch(path, Object.assign({
        credentials: 'same-origin',
        headers: Object.assign({ 'content-type': 'application/json', 'x-csrf-token': csrf }
function esc(s){return String(s==null?'':s).replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));}
, opts.headers || {}),
      }, opts));
      let data = null;
      try { data = await r.json(); } catch { data = null; }
      if (r.status === 403 && data && data.error === 'PLAN_REQUIRED') {
        showUpgrade(data.need);
        return null;
      }
      if (!r.ok) { console.error('api fail', path, r.status, data); return null; }
      return data;
    }

    function showUpgrade(need) {
      document.querySelector('.viewer-shell').innerHTML = `
        <div class="upgrade-banner">
          <h2>Upgrade required</h2>
          <p>This feature is available on the <strong>${esc((need && need.plans || []).join(' or '))}</strong> plan.</p>
          <p>Your current plan: <strong>${esc((need && need.current_plan) || 'free')}</strong></p>
          <a class="button" href="/billing/">See plans →</a>
        </div>
      `;
    }

    async function loadClassification() {
      const r = await api('/findings/' + FINDING_ID + '/classification');
      if (r && r.classification) applyCategory(r.classification);
    }

    async function loadPage() {
      const r = await fetch('/findings/' + FINDING_ID + '/page', { credentials: 'same-origin' });
      if (r.status === 403) {
        const data = await r.json();
        return showUpgrade(data.need);
      }
      if (!r.ok) { document.body.innerHTML = '<div class="upgrade-banner">Fetch failed: HTTP ' + r.status + '</div>'; return; }
      const html = await r.text();
      const src = URL.createObjectURL(new Blob([html], { type: 'text/html' }));
      el('frame').src = src;
      // After load, the iframe's window is the page's window; we can
      // inject a <base> tag to make all relative URLs point at the
      // original source. Use a srcdoc trick instead so the base is
      // respected without a network round-trip.
      el('frame').srcdoc = html.replace('<head>', '<head><base href="' + (r.headers.get('X-Evidence-Source-URL') || '') + '">');
    }

    // ---- toolbar wiring ----
    el('saveBtn').onclick = () => {
      // Direct download — server returns a Content-Disposition: attachment
      window.location.href = '/findings/' + FINDING_ID + '/save.mhtml';
    };

    el('classifyBtn').onclick = async () => {
      el('classifyBtn').disabled = true;
      el('classifyBtn').textContent = '⚙ Classifying…';
      const r = await api('/findings/' + FINDING_ID + '/classify', { method: 'POST', body: JSON.stringify({ includeBody: true }) });
      el('classifyBtn').disabled = false;
      el('classifyBtn').textContent = '⚙ Classify';
      if (r && r.classification) applyCategory(r.classification);
      else if (r === null) {/* plan error — showUpgrade ran */}
      else alert('Classify failed — check console.');
    };

    // In-page search overlay
    el('openSearchBtn').onclick = () => {
      const box = el('inPageSearch');
      box.classList.add('show');
      el('inPageQuery').focus();
    };
    el('inPageClose').onclick = () => el('inPageSearch').classList.remove('show');
    el('inPageNext').onclick = () => {
      const f = el('frame');
      const w = f.contentWindow;
      const q = el('inPageQuery').value;
      if (w.find) {  // legacy API still in Chrome/Edge/FF
        if (!w.find(q, false, false, true, false, false, false)) {
          // wrap
          w.find(q, false, false, true, false, false, true);
        }
      } else {
        alert('In-page search is not available in this browser. Use Ctrl+F inside the page.');
      }
    };
    el('inPageQuery').onkeydown = (e) => { if (e.key === 'Enter') el('inPageNext').click(); };

    // Cross-findings search
    el('crossSearch').onkeydown = (e) => {
      if (e.key !== 'Enter') return;
      const q = el('crossSearch').value.trim();
      if (q.length < 2) return;
      const u = new URL('/findings/search', location.origin);
      u.searchParams.set('case_id', CASE_ID);
      u.searchParams.set('q', q);
      window.open(u.toString(), '_blank', 'noopener');
    };

    // Initial load
    loadPage();
    loadClassification();

    // Re-paint finding URL in the toolbar (server returns it in the iframe's X-Evidence-Source-URL header)
    fetch('/findings/' + FINDING_ID + '/page', { method: 'HEAD', credentials: 'same-origin' }).then(r => {
      el('url').textContent = r.headers.get('X-Evidence-Source-URL') || ('finding #' + FINDING_ID);
    }).catch(() => { el('url').textContent = 'finding #' + FINDING_ID; });
  </script>
</body>
</html>
