"""Flarlo Owner-Dashboard: KI-Video-Überwachung, Klicks, Anmeldungen nach Geschlecht."""

from __future__ import annotations

import json
from pathlib import Path

from jam.jami_owner_dashboard import DEFAULT_API, ensure_admin_secret

ROOT = Path(__file__).resolve().parent.parent
DASHBOARD_DIR = ROOT / "data" / "flarlo-dashboard"
DASHBOARD_HTML = DASHBOARD_DIR / "index.html"
DESKTOP_HTML = Path.home() / "Desktop" / "Flarlo-Owner-Dashboard.html"


def flarlo_api_base() -> str:
    secrets = ROOT / "data" / "jami-secrets.local.json"
    if secrets.is_file():
        try:
            data = json.loads(secrets.read_text(encoding="utf-8"))
            url = (
                str(data.get("flarlo_site_url") or data.get("FLARLO_SITE_URL") or "")
                .strip()
                .rstrip("/")
            )
            if url:
                return url
        except (json.JSONDecodeError, OSError):
            pass
    return "https://flarlo.de"


def dashboard_html(*, api_url: str | None = None) -> str:
    base = (api_url or flarlo_api_base()).rstrip("/")
    return f"""<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="utf-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1"/>
  <title>Flarlo Owner Dashboard</title>
  <style>
    :root {{
      --bg:#050508; --card:rgba(255,255,255,0.06); --border:rgba(255,255,255,0.1);
      --text:#fff; --muted:#9ca3af; --accent:#fe2c55; --mint:#34d399; --warn:#fbbf24; --bad:#f87171;
    }}
    * {{ box-sizing:border-box; }}
    body {{
      margin:0; font-family:system-ui,-apple-system,Segoe UI,sans-serif;
      background:var(--bg); color:var(--text);
      background-image:radial-gradient(ellipse 80% 50% at 50% -10%, rgba(254,44,85,0.22), transparent);
      min-height:100vh; padding:1rem;
    }}
    .wrap {{ max-width:1100px; margin:0 auto; }}
    h1 {{ margin:0 0 0.2rem; font-size:1.55rem; }}
    .sub {{ color:var(--muted); margin:0 0 1.25rem; font-size:0.9rem; }}
    .login, .err {{ display:none; }}
    .login.active, .err.active {{ display:block; }}
    .err {{ background:rgba(248,113,113,0.12); border:1px solid rgba(248,113,113,0.35);
      padding:0.75rem 1rem; border-radius:12px; margin-bottom:1rem; }}
    .login {{
      background:var(--card); border:1px solid var(--border); border-radius:16px;
      padding:1.25rem; max-width:420px;
    }}
    label {{ display:block; font-size:0.85rem; color:var(--muted); margin-bottom:0.35rem; }}
    input {{
      width:100%; padding:0.75rem 1rem; border-radius:12px; border:1px solid var(--border);
      background:rgba(0,0,0,0.35); color:var(--text); font-size:16px; margin-bottom:0.85rem;
    }}
    button {{
      padding:0.75rem 1.1rem; border:none; border-radius:12px; font-weight:700; cursor:pointer;
      background:linear-gradient(135deg,#fe2c55,#ff6b8a); color:#fff;
    }}
    button.secondary {{ background:rgba(255,255,255,0.08); color:var(--text); border:1px solid var(--border); }}
    #panel {{ display:none; }}
    .toolbar {{ display:flex; flex-wrap:wrap; gap:0.5rem; align-items:center; margin-bottom:1rem; }}
    .updated {{ font-size:0.78rem; color:var(--muted); margin-left:auto; }}
    .grid {{
      display:grid; grid-template-columns:repeat(auto-fit,minmax(140px,1fr)); gap:0.75rem;
      margin-bottom:1.1rem;
    }}
    .card {{
      background:var(--card); border:1px solid var(--border); border-radius:14px; padding:0.9rem 1rem;
    }}
    .card .label {{ font-size:0.72rem; color:var(--muted); text-transform:uppercase; letter-spacing:0.04em; }}
    .card .value {{ font-size:1.85rem; font-weight:800; margin-top:0.3rem; line-height:1; }}
    .card .hint {{ font-size:0.72rem; color:var(--muted); margin-top:0.3rem; }}
    .card.warn .value {{ color:var(--warn); }}
    .card.bad .value {{ color:var(--bad); }}
    .card.good .value {{ color:var(--mint); }}
    .section {{
      background:var(--card); border:1px solid var(--border); border-radius:16px;
      padding:1rem 1.1rem 1.2rem; margin-bottom:1.1rem;
    }}
    .section h2 {{ margin:0 0 0.75rem; font-size:1rem; }}
    .meta {{ font-size:0.78rem; color:var(--muted); margin:0 0 0.65rem; }}
    .gender-row {{ display:grid; grid-template-columns:repeat(auto-fit,minmax(120px,1fr)); gap:0.65rem; }}
    .gender-card {{ background:rgba(0,0,0,0.25); border:1px solid var(--border); border-radius:12px; padding:0.75rem; }}
    .gender-card .value {{ font-size:1.6rem; font-weight:800; }}
    .gender-card.frauen .value {{ color:#ff8ec7; }}
    .gender-card.maenner .value {{ color:#82b1ff; }}
    table {{ width:100%; border-collapse:collapse; font-size:0.8rem; }}
    th, td {{ text-align:left; padding:0.4rem 0.35rem; border-bottom:1px solid var(--border); vertical-align:top; }}
    th {{ color:var(--muted); font-size:0.68rem; text-transform:uppercase; }}
    td.num {{ text-align:right; font-variant-numeric:tabular-nums; }}
    .badge {{ display:inline-block; padding:0.15rem 0.45rem; border-radius:999px; font-size:0.68rem; font-weight:700; }}
    .badge.ok {{ background:rgba(52,211,153,0.15); color:var(--mint); }}
    .badge.flagged {{ background:rgba(251,191,36,0.15); color:var(--warn); }}
    .badge.rejected {{ background:rgba(248,113,113,0.15); color:var(--bad); }}
    .scan-thumb {{ width:36px; height:64px; object-fit:cover; border-radius:6px; background:#222; }}
    .flags {{ font-size:0.72rem; color:var(--muted); max-width:220px; }}
    .filter-row {{ display:flex; gap:0.4rem; flex-wrap:wrap; margin-bottom:0.65rem; }}
    .filter-row button {{ font-size:0.78rem; padding:0.4rem 0.7rem; }}
    .filter-row button.active {{ border-color:var(--accent); background:rgba(254,44,85,0.15); }}
    .bars {{ display:flex; align-items:flex-end; gap:0.4rem; height:130px; }}
    .bar-col {{ flex:1; display:flex; flex-direction:column; align-items:center; gap:0.25rem; min-width:0; }}
    .bar {{ width:100%; max-width:36px; border-radius:6px 6px 3px 3px;
      background:linear-gradient(180deg,var(--accent),#9333ea); min-height:3px; }}
    .bar-label {{ font-size:0.6rem; color:var(--muted); }}
    .empty {{ color:var(--muted); font-size:0.85rem; }}
  </style>
</head>
<body>
  <div class="wrap">
    <h1>Flarlo Owner Dashboard</h1>
    <p class="sub">KI-Video-Überwachung · Website-Klicks · Anmeldungen Frauen/Männer</p>
    <div id="err" class="err"></div>
    <div id="login" class="login active">
      <label for="adminKey">Admin-Schlüssel</label>
      <input id="adminKey" type="password" autocomplete="current-password" placeholder="aus data/jami-secrets.local.json"/>
      <button type="button" id="btnLogin">Dashboard öffnen</button>
    </div>
    <div id="panel">
      <div class="toolbar">
        <button type="button" id="btnRefresh">Aktualisieren</button>
        <button type="button" class="secondary" id="btnLogout">Abmelden</button>
        <span class="updated" id="updatedAt"></span>
      </div>
      <div class="grid" id="statsGrid"></div>
      <div class="section">
        <h2>KI-Video-Überwachung</h2>
        <p class="meta">Jedes hochgeladene Video wird per KI gescannt (Bild + Text). Markierte Clips prüfen.</p>
        <div class="filter-row" id="scanFilters">
          <button type="button" data-status="" class="active">Alle</button>
          <button type="button" data-status="flagged">Markiert</button>
          <button type="button" data-status="rejected">Abgelehnt</button>
          <button type="button" data-status="ok">OK</button>
        </div>
        <div id="videoScans"></div>
      </div>
      <div class="section">
        <h2>Flarlo Anmeldungen nach Geschlecht</h2>
        <p class="meta" id="flarloGenderMeta"></p>
        <div class="gender-row" id="flarloGenderRow"></div>
      </div>
      <div class="section">
        <h2>Flarlo Website-Klicks</h2>
        <div class="grid" id="flarloClickGrid"></div>
        <div class="bars" id="flarloChart" style="margin-top:0.75rem"></div>
      </div>
      <div class="section">
        <h2>Gesamt (alle Projekte)</h2>
        <p class="meta">Mitglieder &amp; Traffic über Jami + Flarlo</p>
        <div class="gender-row" id="allGenderRow"></div>
      </div>
    </div>
  </div>
  <script>
    const API = {json.dumps(base)};
    const KEY_STORAGE = 'flarlo_admin_key_v1';
    let scanFilter = '';
    const errEl = document.getElementById('err');
    const loginEl = document.getElementById('login');
    const panelEl = document.getElementById('panel');
    const keyInput = document.getElementById('adminKey');

    function showErr(msg) {{
      errEl.textContent = msg;
      errEl.classList.add('active');
    }}
    function clearErr() {{ errEl.classList.remove('active'); errEl.textContent = ''; }}
    function fmt(n) {{ return Number(n || 0).toLocaleString('de-DE'); }}

    async function apiGet(path, key) {{
      const r = await fetch(API + path, {{ headers: {{ 'X-Jami-Admin': key }} }});
      const j = await r.json().catch(() => ({{}}));
      if (!r.ok) throw new Error(j.error || ('HTTP ' + r.status));
      return j;
    }}

    function renderGenderRow(elId, g) {{
      const all = g?.all || {{}};
      document.getElementById(elId).innerHTML = [
        ['Frauen', all.frauen, 'frauen'],
        ['Männer', all.maenner, 'maenner'],
        ['Divers', all.divers, 'divers'],
      ].map(function(row) {{
        return '<div class="gender-card ' + row[2] + '"><div class="label">' + row[0] +
          '</div><div class="value">' + fmt(row[1]) + '</div></div>';
      }}).join('');
    }}

    function statusBadge(s) {{
      const c = s === 'ok' ? 'ok' : (s === 'rejected' ? 'rejected' : 'flagged');
      return '<span class="badge ' + c + '">' + (s || '?') + '</span>';
    }}

    function esc(s) {{
      const d = document.createElement('div');
      d.textContent = s || '';
      return d.innerHTML;
    }}

    function renderScans(scans) {{
      const el = document.getElementById('videoScans');
      if (!scans || !scans.length) {{
        el.innerHTML = '<p class="empty">Noch keine Video-Scans – kommt mit dem ersten Upload.</p>';
        return;
      }}
      let html = '<table><thead><tr><th></th><th>Status</th><th>Risiko</th><th>Creator</th><th>Text</th><th>Flags</th><th>Zeit</th></tr></thead><tbody>';
      scans.forEach(function(s) {{
        const flags = (s.flags || []).map(function(f) {{ return f.reason || f.type || ''; }}).filter(Boolean).join('; ');
        const thumb = s.thumbUrl ? '<img class="scan-thumb" src="' + esc(s.thumbUrl) + '" alt="">' : '–';
        const user = '@' + (s.author?.username || s.author?.displayName || '?');
        html += '<tr><td>' + thumb + '</td><td>' + statusBadge(s.scanStatus) + '</td>' +
          '<td class="num">' + Math.round(s.riskScore || 0) + '</td>' +
          '<td>' + esc(user) + '</td>' +
          '<td>' + esc((s.caption || '').slice(0, 80)) + '</td>' +
          '<td class="flags">' + esc(flags || '–') + '</td>' +
          '<td>' + esc((s.createdAt || '').replace('T', ' ').slice(0, 16)) + '</td></tr>';
      }});
      html += '</tbody></table>';
      el.innerHTML = html;
    }}

    function renderStats(d, scans) {{
      const vm = d.videoModeration || {{}};
      const fl = d.flarlo || {{}};
      document.getElementById('statsGrid').innerHTML = [
        ['Videos gescannt', vm.total, 'gesamt', ''],
        ['Scans heute', vm.today, 'KI-Überwachung', ''],
        ['Markiert', vm.flagged, 'zur Prüfung', 'warn'],
        ['Abgelehnt', vm.rejected, 'hohes Risiko', 'bad'],
        ['Ø Risiko 7T', vm.avgRiskWeek, '0–100', ''],
        ['Flarlo Aufrufe', fl.pageViews?.today ?? 0, 'heute', 'good'],
        ['Reg.-Klicks', fl.registerClicks?.today ?? 0, 'heute', ''],
        ['Neue Flarlo', fl.registrations?.today ?? 0, 'heute', 'good'],
      ].map(function(c) {{
        return '<div class="card ' + (c[3] || '') + '"><div class="label">' + c[0] +
          '</div><div class="value">' + fmt(c[1]) + '</div><div class="hint">' + c[2] + '</div></div>';
      }}).join('');

      const fg = fl.gender || {{}};
      const ft = fg.today || {{}};
      const fw = fg.week || {{}};
      document.getElementById('flarloGenderMeta').textContent =
        'Heute: ' + fmt(ft.frauen) + ' Frauen · ' + fmt(ft.maenner) + ' Männer · ' +
        fmt(ft.divers) + ' divers · Woche: ' + fmt(fw.total) + ' gesamt';
      renderGenderRow('flarloGenderRow', fg);
      renderGenderRow('allGenderRow', d.gender || {{}});

      document.getElementById('flarloClickGrid').innerHTML = [
        ['Aufrufe Woche', fl.pageViews?.week ?? 0],
        ['Klicks „Registrieren“ Woche', fl.registerClicks?.week ?? 0],
        ['Anmeldungen Woche', fl.registrations?.week ?? 0],
        ['Anmeldungen gesamt', fl.registrations?.total ?? 0],
      ].map(function(c) {{
        return '<div class="card"><div class="label">' + c[0] + '</div><div class="value">' + fmt(c[1]) + '</div></div>';
      }}).join('');

      const days = d.last7Days || [];
      const max = Math.max(1, ...days.map(function(x) {{ return x.pageViews || 0; }}));
      document.getElementById('flarloChart').innerHTML = days.map(function(row) {{
        const h = Math.round(((row.pageViews || 0) / max) * 110);
        return '<div class="bar-col"><div class="bar" style="height:' + h + 'px"></div>' +
          '<div class="bar-label">' + (row.day || '').slice(5) + '</div></div>';
      }}).join('');

      renderScans(scans);
      document.getElementById('updatedAt').textContent = 'Stand: ' + (d.updatedAt || '').replace('T', ' ').slice(0, 19);
    }}

    async function loadDashboard() {{
      clearErr();
      const key = (keyInput.value || localStorage.getItem(KEY_STORAGE) || '').trim();
      if (!key) {{ showErr('Bitte Admin-Schlüssel eingeben.'); return; }}
      try {{
        const q = scanFilter ? ('?status=' + encodeURIComponent(scanFilter)) : '';
        const [stats, scansData] = await Promise.all([
          apiGet('/api/admin/dashboard', key),
          apiGet('/api/admin/video-scans' + q + (q ? '&' : '?') + 'limit=50', key),
        ]);
        localStorage.setItem(KEY_STORAGE, key);
        loginEl.classList.remove('active');
        panelEl.style.display = 'block';
        renderStats(stats, scansData.scans || []);
      }} catch (e) {{
        showErr(e.message || String(e));
      }}
    }}

    document.getElementById('btnLogin').addEventListener('click', loadDashboard);
    document.getElementById('btnRefresh').addEventListener('click', loadDashboard);
    document.getElementById('btnLogout').addEventListener('click', function() {{
      localStorage.removeItem(KEY_STORAGE);
      keyInput.value = '';
      panelEl.style.display = 'none';
      loginEl.classList.add('active');
    }});
    document.querySelectorAll('#scanFilters button').forEach(function(btn) {{
      btn.addEventListener('click', function() {{
        document.querySelectorAll('#scanFilters button').forEach(function(b) {{ b.classList.remove('active'); }});
        btn.classList.add('active');
        scanFilter = btn.dataset.status || '';
        loadDashboard();
      }});
    }});
    keyInput.addEventListener('keydown', function(e) {{ if (e.key === 'Enter') loadDashboard(); }});
    if (localStorage.getItem(KEY_STORAGE)) {{
      keyInput.value = localStorage.getItem(KEY_STORAGE);
      loadDashboard();
    }}
    setInterval(loadDashboard, 60000);
  </script>
</body>
</html>"""


def write_dashboard_files(*, api_url: str | None = None) -> tuple[Path, Path]:
    html = dashboard_html(api_url=api_url)
    DASHBOARD_DIR.mkdir(parents=True, exist_ok=True)
    DASHBOARD_HTML.write_text(html, encoding="utf-8")
    DESKTOP_HTML.write_text(html, encoding="utf-8")
    return DASHBOARD_HTML, DESKTOP_HTML


def write_setup_note(secret: str) -> Path:
    note = ROOT / "data" / "FLARLO_DASHBOARD.txt"
    note.write_text(
        f"""FLARLO OWNER DASHBOARD
========================

Dashboard öffnen:
  python scripts/flarlo_dashboard.py

Oder Datei im Browser:
  Desktop\\Flarlo-Owner-Dashboard.html

Admin-Schlüssel (geheim halten):
  {secret}

Steht in: data/jami-secrets.local.json → jami_admin_secret

API:
  {flarlo_api_base()}/api/admin/dashboard
  {flarlo_api_base()}/api/admin/video-scans

Features:
  - KI-Scan jedes Video-Uploads (Thumbnail + Beschreibung)
  - Markierte / abgelehnte Clips
  - Flarlo Website-Klicks & Anmeldungen
  - Geschlecht: Frauen / Männer / divers
""",
        encoding="utf-8",
    )
    return note
