<!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>Cases — takedowns</title>
  <link rel="stylesheet" href="/public/css/glass.css?v=2-light" />
  <style>
    .scan-progress { padding: .75rem; background: var(--bg-3); border-radius: 6px; margin-bottom: 1rem; }
    .scan-progress .bar { background: var(--bg-2); height: 6px; border-radius: 3px; overflow: hidden; margin-top: .35rem; }
    .scan-progress .bar > span { display: block; height: 100%; background: var(--accent); width: 0; transition: width .3s; }
    .pp-row { padding: .65rem; border-bottom: 1px solid var(--border); }
    .pp-row:hover { background: var(--bg-3); }
    .pp-row .url { font-family: var(--mono); font-size: .8rem; word-break: break-all; }
  </style>
</head>
<body>
  <div class="app">
    <aside>
      <a href="/" class="brand" aria-label="takedowns home"><img src="/public/og/logo-mark.png" alt="" width="28" height="28" /><span class="brand-wordmark">takedowns<small>by vesamuni</small></span></a>
      <nav>
        <a href="/dashboard/">Dashboard</a>
        <a href="/cases/" class="active">My cases</a>
        <a href="/scan/">Run a scan</a>
        <a href="/takedown/">Takedowns</a>
        <a href="/billing/">Billing &amp; plan</a>
        <a href="/admin/" data-admin-only class="hidden">Admin panel</a>
        <a href="#" id="logout">Sign out</a>
      </nav>
    </aside>
    <main>
      <header class="topbar">
        <h1>Cases</h1>
        <div class="user-pill">
          <button id="newCase">+ New case</button>
          <span id="siteHealthDot" class="site-health-dot unknown" title="checking…"></span>
        </div>
      </header>
      <div id="flash"></div>

      <!-- Deep discovery panel (per case) -->
      <section class="panel" id="discoverPanel" style="display:none">
        <div class="between">
          <h2>Deep discovery scan</h2>
          <div class="flex">
            <button id="startScanBtn" class="secondary">Run deep discovery</button>
            <button id="cancelScanBtn" class="secondary" style="display:none">Cancel</button>
          </div>
        </div>
        <div class="muted" style="margin-bottom:.75rem">
          Searches Google for every public mention of the victim, validates each hit
          (HTTP 200 + name + NCII term + image probe), runs contact discovery + RDAP
          on each domain, and queues a production-pending takedown per site.
          Typical run: 50-100 sites, 2-5 minutes, 500-700 scan credits.
        </div>
        <div id="scansList">
          <div class="muted">No scans yet.</div>
        </div>
      </section>

      <!-- Production-pending takedowns (per case) -->
      <section class="panel" id="ppPanel" style="display:none">
        <div class="between">
          <h2>Production-pending takedowns <span class="muted" id="ppCount"></span></h2>
          <div class="muted">Awaiting real Resend keys. Click "Send all" once keys are configured in /admin → API keys.</div>
        </div>
        <div id="ppList">
          <div class="muted">No pending takedowns.</div>
        </div>
      </section>

      <!-- Findings + evidence workspace (per case) -->
      <section class="panel" id="findingsPanel" style="display:none">
        <div class="between">
          <h2>Findings &amp; evidence <span class="muted" id="findingsCount"></span></h2>
          <div class="flex">
            <a id="openSearch" class="pill" target="_blank" rel="noopener">🔍 Search across findings…</a>
          </div>
        </div>
        <div class="muted" style="margin-bottom:.5rem;font-size:.85rem">
          Each finding is a confirmed leak. Open it in the viewer to <b>see the page</b>,
          <b>save a self-contained MHTML</b>, <b>classify with AI</b>, and
          <b>search within the page</b>. AI categorization is Pro+Agency only —
          on lower plans the buttons are replaced with a one-click upgrade hint.
        </div>
        <div id="findingsList">
          <div class="muted">No findings yet.</div>
        </div>
      </section>

      <div class="panel">
        <table class="tight">
          <thead><tr><th>ID</th><th>Victim</th><th>Status</th><th>Reference URL</th><th>Created</th><th></th></tr></thead>
          <tbody id="rows"></tbody>
        </table>
      </div>

      <!-- New case modal -->
      <div id="modal" class="hidden" style="position:fixed;inset:0;background:rgba(0,0,0,.6);display:flex;align-items:center;justify-content:center;z-index:99">
        <div class="panel" style="width:100%;max-width:520px">
          <h2>New case</h2>
          <form id="newForm">
            <label>Victim name (as it appears online)</label>
            <input name="victim_name" required minlength="2" />
            <label>Reference URL (proof, original source, etc.)</label>
            <input name="reference_url" type="url" placeholder="https://" />
            <label>Context (notes, instructions, who is involved)</label>
            <textarea name="context" rows="3"></textarea>
            <div class="muted" style="margin-top:.5rem;font-size:.8rem">
              A deep discovery scan will run automatically after this case is created.
            </div>
            <div class="row mt-2">
              <button type="submit">Create case &amp; start discovery</button>
              <button type="button" class="secondary" id="cancel">Cancel</button>
            </div>
          </form>
        </div>
      </div>
    </main>
  </div>

  <script>
    function csrf(){const m=document.cookie.match(/(?:^|; )ncsrf=([^;]+)/);return m?m[1]:'';}
    async function api(p,o={}){const r=await fetch(p,{...o,headers:{'content-type':'application/json','x-csrf-token':csrf(),...(o.headers||{})}});if(r.status===401){location.href='/login?next='+encodeURIComponent(location.pathname);return null;}return r.json().catch(()=>({}));}
    function esc(s){return String(s||'').replace(/[&<>"]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c]));}
    function flash(t,m){document.getElementById('flash').innerHTML=`<div class="flash ${esc(t)}">${esc(m)}</div>`;setTimeout(()=>document.getElementById('flash').innerHTML='',6000);}

    let currentCaseId = null;
    function getCaseIdFromUrl() {
      const m = location.search.match(/[?&]id=(\d+)/);
      return m ? parseInt(m[1], 10) : null;
    }

    async function loadCases() {
      const d = await api('/cases/');
      if (!d) return;
      const tb = document.getElementById('rows');
      tb.innerHTML = d.cases.map(c => `
        <tr>
          <td>${c.id}</td>
          <td>${esc(c.victim_name)}</td>
          <td><span class="pill ${c.status==='open'?'warn':c.status==='closed'?'ok':'info'}">${c.status}</span></td>
          <td>${c.reference_url?`<a href="${esc(c.reference_url)}" target="_blank" rel="noopener">link</a>`:'<span class="muted">—</span>'}</td>
          <td class="muted mono">${new Date(c.created_at).toLocaleDateString()}</td>
          <td><a href="?id=${c.id}#discover">discover</a> · <a href="/scan/?case_id=${c.id}">scan</a> · <a href="/takedown/?case_id=${c.id}">takedown</a></td>
        </tr>`).join('') || `<tr><td colspan="6" class="muted center">No cases yet.</td></tr>`;

      // If ?id=X, show the deep discovery + production-pending panels
      currentCaseId = getCaseIdFromUrl();
      if (currentCaseId) {
        document.getElementById('discoverPanel').style.display = '';
        document.getElementById('ppPanel').style.display = '';
        document.getElementById('findingsPanel').style.display = '';
        const searchLink = document.getElementById('openSearch');
        searchLink.href = `/findings/search?case_id=${currentCaseId}`;
        loadScans();
        loadProductionPending();
        loadFindings();
      }
    }

    async function loadScans() {
      if (!currentCaseId) return;
      const d = await api(`/cases/${currentCaseId}/discover`);
      if (!d) return;
      const block = document.getElementById('scansList');
      if (!d.scans.length) { block.innerHTML = '<div class="muted">No scans yet. Click "Run deep discovery".</div>'; return; }
      block.innerHTML = d.scans.map(s => {
        const pct = s.status === 'done' ? 100 : s.status === 'failed' ? 0 : 50;
        return `
          <div class="scan-progress">
            <div class="flex between">
              <div>
                <b>Scan #${s.id}</b> <span class="pill ${s.status==='done'?'ok':s.status==='failed'?'danger':'info pulse'}">${s.status}</span>
                <span class="muted" style="margin-left:.5rem">${new Date(s.created_at).toLocaleString()}</span>
              </div>
              <div class="muted">${esc(s.progress || '')}</div>
            </div>
            <div class="bar"><span style="width:${pct}%"></span></div>
            <div class="muted" style="margin-top:.5rem;font-size:.85rem">
              queries: ${s.queries ? JSON.parse(s.queries).length : '—'} ·
              candidates: ${s.candidates} ·
              validated: ${s.validated} ·
              false positives: ${s.false_positives} ·
              queued: ${s.queued_pp} ·
              deduped: ${s.deduped || 0} ·
              no contact: ${s.no_contact}
            </div>
          </div>`;
      }).join('');
    }

    async function loadProductionPending() {
      if (!currentCaseId) return;
      // We need a global list of PP takedowns filtered by case_id
      const d = await api('/admin/production-pending');
      if (!d) return;
      const rows = d.takedowns.filter(t => t.case_id === currentCaseId);
      document.getElementById('ppCount').textContent = `(${rows.length})`;
      if (!rows.length) { document.getElementById('ppList').innerHTML = '<div class="muted">No pending takedowns.</div>'; return; }
      document.getElementById('ppList').innerHTML = rows.map(t => `
        <div class="pp-row flex between">
          <div class="grow">
            <div class="url"><a href="${esc(t.url)}" target="_blank" rel="noopener">${esc(t.url)}</a></div>
            <div class="muted" style="font-size:.8rem">
              → <span class="mono">${esc(t.contact_email || '(chain-only)')}</span>
              · method=${esc(t.draft_method)}
            </div>
          </div>
          <div class="muted" style="font-size:.8rem">${new Date(t.created_at).toLocaleString()}</div>
        </div>`).join('');
    }

    // ---- findings + evidence ----
    const CATEGORY_PILLS = {
      unauthorized_video: ['video', 'unauthorized video'],
      unauthorized_image: ['image', 'unauthorized image'],
      unauthorized_other: ['other', 'unauthorized (other)'],
      name_only:          ['name',  'name only'],
      not_ncii:           ['ok',    'not NCII'],
      unknown:            ['unknown', 'unknown'],
    };
    function categoryPill(c) {
      if (!c) return '<span class="muted">— not classified —</span>';
      const meta = CATEGORY_PILLS[c.category] || ['unknown', c.category];
      return `<span class="pill ${meta[0]}" title="${esc(c.evidence||'')}">${meta[1]} · ${Math.round((c.confidence||0)*100)}%</span>`;
    }

    async function loadFindings() {
      if (!currentCaseId) return;
      const d = await api(`/cases/${currentCaseId}/findings`);
      if (!d) return;
      const rows = d.findings || [];
      document.getElementById('findingsCount').textContent = `(${rows.length})`;
      const block = document.getElementById('findingsList');
      if (!rows.length) { block.innerHTML = '<div class="muted">No findings yet — run a deep discovery scan.</div>'; return; }
      block.innerHTML = rows.map(f => {
        const viewer = `/findings/${f.id}/view?case_id=${currentCaseId}`;
        const mhtml  = `/findings/${f.id}/save.mhtml`;
        const cls    = f.classification;
        const cat = categoryPill(cls);
        return `
          <div class="pp-row" style="display:flex;gap:.75rem;align-items:flex-start;justify-content:space-between">
            <div class="grow" style="min-width:0">
              <div class="url" style="font-family:var(--mono);font-size:.85rem">
                <a href="${esc(f.url)}" target="_blank" rel="noopener">${esc(f.url)}</a>
              </div>
              <div class="muted" style="font-size:.8rem;margin-top:.15rem">
                T${f.tier} · status: ${f.status} · ${cat}
                ${cls && cls.summary ? ` · <i>${esc(cls.summary)}</i>` : ''}
              </div>
            </div>
            <div class="flex" style="flex:0">
              <a class="pill" target="_blank" rel="noopener" href="${viewer}" title="Open in the page viewer (MHTML iframe + Ctrl+F)">👁 Open</a>
              <a class="pill" target="_blank" rel="noopener" href="${mhtml}"  title="Download a self-contained .mhtml">⬇ .mhtml</a>
              <button class="pill" data-classify="${f.id}" title="Run AI categorization (one call)">⚙ Classify</button>
            </div>
          </div>`;
      }).join('');
      // Wire per-row classify buttons
      block.querySelectorAll('[data-classify]').forEach(btn => {
        btn.onclick = async () => {
          btn.disabled = true; btn.textContent = '⚙ …';
          const r = await api(`/findings/${btn.dataset.classify}/classify`, { method: 'POST', body: JSON.stringify({ includeBody: true }) });
          btn.disabled = false; btn.textContent = '⚙ Classify';
          if (r && r.classification) {
            flash('ok', `Classified: ${r.classification.category} (${Math.round(r.classification.confidence*100)}%)`);
            loadFindings();
          } else if (r && r.error === 'PLAN_REQUIRED') {
            flash('err', 'AI classify is a Pro+Agency feature. Upgrade at /billing/.');
          } else {
            flash('err', 'Classify failed — see alert log.');
          }
        };
      });
    }

    document.getElementById('newCase').onclick = () => document.getElementById('modal').classList.remove('hidden');
    document.getElementById('cancel').onclick = () => document.getElementById('modal').classList.add('hidden');
    document.getElementById('newForm').onsubmit = async (e) => {
      e.preventDefault();
      const body = Object.fromEntries(new FormData(e.target));
      const r = await api('/cases/', { method: 'POST', body: JSON.stringify(body) });
      if (r && r.ok) {
        flash('ok', r.auto_discovery ? 'Case created — deep discovery scan is running.' : 'Case created.');
        document.getElementById('modal').classList.add('hidden');
        // Open the new case
        location.href = `?id=${r.case.id}#discover`;
      } else flash('err', (r && (r.message||r.error)) || 'Failed');
    };

    document.getElementById('startScanBtn').onclick = async () => {
      if (!currentCaseId) return;
      const r = await api(`/cases/${currentCaseId}/discover`, { method: 'POST' });
      if (r && r.ok) { flash('ok', 'Scan queued.'); loadScans(); startScanPolling(); }
      else flash('err', (r && (r.message||r.error)) || 'Failed');
    };
    document.getElementById('cancelScanBtn').onclick = async () => {
      // Find the running scan
      const d = await api(`/cases/${currentCaseId}/discover`);
      const running = d.scans.find(s => s.status === 'running' || s.status === 'queued');
      if (running) {
        await api(`/cases/${currentCaseId}/discover/${running.id}/cancel`, { method: 'POST' });
        flash('info', 'Scan cancelled.'); loadScans();
      }
    };

    let scanPoll = null;
    function startScanPolling() {
      if (scanPoll) return;
      scanPoll = setInterval(async () => {
        await loadScans();
        const d = await api(`/cases/${currentCaseId}/discover`);
        const anyActive = d.scans.some(s => s.status === 'running' || s.status === 'queued');
        if (!anyActive) { stopScanPolling(); loadProductionPending(); }
      }, 4000);
    }
    function stopScanPolling() { if (scanPoll) { clearInterval(scanPoll); scanPoll = null; } }

    document.getElementById('logout').onclick = async (e) => { e.preventDefault(); await api('/auth/logout', { method: 'POST' }); location.href = '/'; };

    loadCases().then(() => {
      // If we just opened with a case id, start polling
      if (currentCaseId) {
        const d = fetch(`/cases/${currentCaseId}/discover`).then(r => r.json());
        d.then(j => { if (j.scans && j.scans.some(s => s.status === 'running' || s.status === 'queued')) startScanPolling(); });
      }
    });
  </script>
  <script src="/public/js/siteHealth.js" defer></script>
</body>
</html>
