// ============================================
// Reliq — Dashboard
// ============================================

// ── Enriched scan data (split version/build for export) ──────────────────────
const DASHBOARD_SCANS = [
  { id:"scn_2k8x", app:"Roamly",       letters:"R", grad:"linear-gradient(135deg,#5B9DFF,#A78BFA)",
    bundle:"com.roamly.app",           version:"1.4.0", build:"142",
    stores:["play","app"], score:92, verdict:"pass",
    crit:0, warn:1, info:0, source:"github",  date:"2026-05-22", when:"12 min ago" },
  { id:"scn_2k8w", app:"QuickInvoice", letters:"Q", grad:"linear-gradient(135deg,#F59E0B,#EF4444)",
    bundle:"com.quickinvoice.android", version:"2.1.3", build:"87",
    stores:["play"],        score:64, verdict:"needs_fixes",
    crit:1, warn:5, info:0, source:"manual",  date:"2026-05-22", when:"1 hour ago" },
  { id:"scn_2k8v", app:"MoodBoard AI", letters:"M", grad:"linear-gradient(135deg,#A78BFA,#EF4444)",
    bundle:"com.moodboard.ai",         version:"0.9.2", build:"28",
    stores:["play","app"], score:41, verdict:"will_reject",
    crit:3, warn:8, info:1, source:"github",  date:"2026-05-22", when:"3 hours ago" },
  { id:"scn_2k8u", app:"TidalFlow",    letters:"T", grad:"linear-gradient(135deg,#00D4AA,#5B9DFF)",
    bundle:"com.tidalflow.app",        version:"3.0.1", build:"201",
    stores:["app"],         score:88, verdict:"pass",
    crit:0, warn:2, info:0, source:"api",     date:"2026-05-21", when:"Yesterday, 16:42" },
  { id:"scn_2k8t", app:"Pocket Coach", letters:"P", grad:"linear-gradient(135deg,#5B9DFF,#00D4AA)",
    bundle:"com.pocket.coach",         version:"1.0.0", build:"12",
    stores:["play","app"], score:76, verdict:"likely_pass",
    crit:0, warn:3, info:1, source:"manual",  date:"2026-05-21", when:"Yesterday, 09:11" },
  { id:"scn_2k8s", app:"Brewline",     letters:"B", grad:"linear-gradient(135deg,#F59E0B,#A78BFA)",
    bundle:"com.brewline.app",         version:"4.2.1", build:"312",
    stores:["play"],        score:95, verdict:"pass",
    crit:0, warn:0, info:0, source:"bitrise", date:"2026-05-20", when:"2 days ago" },
];

// ── Failure types data (stores used for store-filter passthrough) ─────────────
const DASHBOARD_FAILURE_TYPES = [
  { cat:"Privacy Manifest",    n:18, sev:"critical", pct:78, stores:["app"] },
  { cat:"Misleading Metadata", n:12, sev:"warning",  pct:55, stores:["play","app"] },
  { cat:"Tracking Permissions",n:9,  sev:"warning",  pct:42, stores:["play","app"] },
  { cat:"Hardcoded Secrets",   n:7,  sev:"critical", pct:32, stores:["play","app"] },
  { cat:"Screenshot Sizes",    n:5,  sev:"info",     pct:22, stores:["play","app"] },
];

const DEFAULT_FILTERS = {
  dateRange:"all", app:"all", store:"all",
  verdict:"all", severity:"all", source:"all",
};

// ── Verdict components (shared via window) ────────────────────────────────────
const verdictMeta = {
  pass:        { label:"PASS",        color:"var(--teal)",  bg:"var(--teal-bg)"  },
  likely_pass: { label:"LIKELY PASS", color:"var(--blue)",  bg:"var(--blue-bg)"  },
  needs_fixes: { label:"NEEDS FIXES", color:"var(--amber)", bg:"var(--amber-bg)" },
  will_reject: { label:"WILL REJECT", color:"var(--red)",   bg:"var(--red-bg)"   },
};

const VerdictPill = ({ verdict }) => {
  const m = verdictMeta[verdict];
  return (
    <span style={{
      display:"inline-flex", alignItems:"center", gap:6,
      fontFamily:"var(--font-mono)", fontSize:10.5, fontWeight:600,
      letterSpacing:"0.08em", padding:"3px 8px", borderRadius:4, whiteSpace:"nowrap",
      color:m.color, background:m.bg, border:`1px solid ${m.color}40`
    }}>
      <span style={{width:6, height:6, borderRadius:"50%", background:m.color, boxShadow:`0 0 6px ${m.color}`}} />
      {m.label}
    </span>
  );
};

// ── Helper: download a blob ───────────────────────────────────────────────────
const downloadBlob = (content, filename, type) => {
  const blob = new Blob([content], { type });
  const url  = URL.createObjectURL(blob);
  const a    = Object.assign(document.createElement("a"), { href:url, download:filename });
  a.click();
  URL.revokeObjectURL(url);
};

const TODAY = "2026-05-23";

// ── Dashboard ─────────────────────────────────────────────────────────────────
const Dashboard = ({ go }) => {

  // ── State ────────────────────────────────────────────────────────────────────
  const [filters,        setFilters]        = React.useState(DEFAULT_FILTERS);
  const [pendingFilters, setPendingFilters] = React.useState(DEFAULT_FILTERS);
  const [exportOpen,     setExportOpen]     = React.useState(false);
  const [filterOpen,     setFilterOpen]     = React.useState(false);
  const [exportLoading,  setExportLoading]  = React.useState(null);

  const exportWrapRef = React.useRef(null);
  const filterWrapRef = React.useRef(null);

  // ── Toast (delegates to global reliqToast) ───────────────────────────────────
  const showToast = React.useCallback((msg, type = "success") => {
    if (type === "error") window.reliqToast?.error(msg);
    else                  window.reliqToast?.success(msg);
  }, []);

  // ── Click-outside / Escape ───────────────────────────────────────────────────
  React.useEffect(() => {
    const onMouse = (e) => {
      if (exportOpen && exportWrapRef.current && !exportWrapRef.current.contains(e.target)) setExportOpen(false);
      if (filterOpen && filterWrapRef.current && !filterWrapRef.current.contains(e.target)) setFilterOpen(false);
    };
    const onKey = (e) => {
      if (e.key === "Escape") { setExportOpen(false); setFilterOpen(false); }
    };
    document.addEventListener("mousedown", onMouse);
    window.addEventListener("keydown", onKey);
    return () => {
      document.removeEventListener("mousedown", onMouse);
      window.removeEventListener("keydown", onKey);
    };
  }, [exportOpen, filterOpen]);

  // ── Filtered data ─────────────────────────────────────────────────────────────
  const filteredScans = React.useMemo(() => {
    const today = new Date(TODAY);
    return DASHBOARD_SCANS.filter(s => {
      if (filters.app    !== "all" && s.app    !== filters.app)    return false;
      if (filters.verdict !== "all" && s.verdict !== filters.verdict) return false;
      if (filters.source  !== "all" && s.source  !== filters.source)  return false;
      if (filters.store !== "all") {
        if (filters.store === "play" && !s.stores.includes("play")) return false;
        if (filters.store === "app"  && !s.stores.includes("app"))  return false;
        if (filters.store === "both" && !(s.stores.includes("play") && s.stores.includes("app"))) return false;
      }
      if (filters.severity !== "all") {
        if (filters.severity === "critical" && s.crit === 0) return false;
        if (filters.severity === "warning"  && s.warn === 0) return false;
        if (filters.severity === "info"     && s.info === 0) return false;
      }
      if (filters.dateRange !== "all") {
        const d    = new Date(s.date);
        const diff = Math.floor((today - d) / 86400000);
        if (filters.dateRange === "7d"         && diff > 7)  return false;
        if (filters.dateRange === "30d"        && diff > 30) return false;
        if (filters.dateRange === "this_month" && (d.getMonth() !== today.getMonth() || d.getFullYear() !== today.getFullYear())) return false;
        if (filters.dateRange === "last_month") {
          const lm = new Date(today.getFullYear(), today.getMonth() - 1, 1);
          if (d.getMonth() !== lm.getMonth() || d.getFullYear() !== lm.getFullYear()) return false;
        }
      }
      return true;
    });
  }, [filters]);

  const filteredFailures = React.useMemo(() => {
    return DASHBOARD_FAILURE_TYPES.filter(f => {
      if (filters.store === "play" && !f.stores.includes("play")) return false;
      if (filters.store === "app"  && !f.stores.includes("app"))  return false;
      if (filters.severity !== "all" && f.sev !== filters.severity) return false;
      return true;
    });
  }, [filters]);

  // ── Computed stats ────────────────────────────────────────────────────────────
  const metrics = React.useMemo(() => {
    const n       = filteredScans.length;
    const passing = filteredScans.filter(s => s.verdict === "pass" || s.verdict === "likely_pass").length;
    const passRate = n > 0 ? Math.round((passing / n) * 100) : 0;
    const avgScore = n > 0 ? Math.round(filteredScans.reduce((a, s) => a + s.score, 0) / n) : 0;
    const top      = filteredFailures[0] || null;
    const topParts = top ? top.cat.split(" ") : [];
    return {
      count: n, passRate, avgScore,
      topVal:  top ? topParts[0]                               : "—",
      topUnit: top ? " " + topParts.slice(1).join(" ").toLowerCase() : "",
    };
  }, [filteredScans, filteredFailures]);

  const activeFilterCount = Object.values(filters).filter(v => v !== "all").length;
  const isFiltered        = activeFilterCount > 0;

  const stats = [
    { lbl:"Scans this month", val:String(metrics.count),    unit:"/ 100", trend:"up", change: isFiltered ? "filtered view" : "+12 vs last", spark:[3,5,4,7,6,9,8,11,10,14,12,15] },
    { lbl:"Pass rate",        val:String(metrics.passRate), unit:"%",     trend:"up", change: isFiltered ? "filtered view" : "+6% vs last",  spark:[60,62,65,68,66,70,72,74,75,76,78,78] },
    { lbl:"Most common",      val:metrics.topVal,           unit:metrics.topUnit, trend:"dn", change: isFiltered ? "filtered view" : "8 hits today", spark:[4,3,5,7,6,8,9,8,10,9,11,8] },
    { lbl:"Avg score",        val:String(metrics.avgScore), unit:"/ 100", trend:"up", change: isFiltered ? "filtered view" : "+4 vs last",   spark:[70,71,72,71,73,74,75,75,76,75,77,76] },
  ];

  // ── Export functions ──────────────────────────────────────────────────────────
  const exportScansCSV = () => {
    const hdr  = ["scan_id","app_name","bundle","version","build","stores","verdict","score","critical_issues","warning_issues","info_issues","source","scan_date"];
    const rows = filteredScans.map(s => [s.id,s.app,s.bundle,s.version,s.build,s.stores.join("|"),s.verdict,s.score,s.crit,s.warn,s.info,s.source,s.date]);
    downloadBlob([hdr,...rows].map(r=>r.map(v=>`"${v}"`).join(",")).join("\n"), `reliq-recent-scans-${TODAY}.csv`, "text/csv");
  };

  const exportScansJSON = () => {
    const data = filteredScans.map(s => ({
      scan_id:s.id, app_name:s.app, bundle:s.bundle, version:s.version, build:s.build,
      stores:s.stores, verdict:s.verdict, score:s.score,
      critical_issues:s.crit, warning_issues:s.warn, info_issues:s.info,
      source:s.source, scan_date:s.date,
    }));
    downloadBlob(
      JSON.stringify({ exported_at:TODAY, filters_applied: isFiltered ? filters : null, scans:data }, null, 2),
      `reliq-recent-scans-${TODAY}.json`, "application/json"
    );
  };

  const exportFailuresCSV = () => {
    const hdr  = ["failure_type","severity","count","percentage","period"];
    const rows = filteredFailures.map(f => [f.cat, f.sev, f.n, f.pct+"%", "Last 30 days"]);
    downloadBlob([hdr,...rows].map(r=>r.map(v=>`"${v}"`).join(",")).join("\n"), `reliq-failure-types-${TODAY}.csv`, "text/csv");
  };

  const exportDashboardPDF = () => {
    const filterNote = isFiltered
      ? `<p style="font-size:12px;color:#888;margin:0 0 16px;padding:8px 12px;background:#fffbeb;border:1px solid #f59e0b;border-radius:6px">
           Filters active: ${Object.entries(filters).filter(([,v])=>v!=="all").map(([k,v])=>`<b>${k}</b> = ${v}`).join(" · ")}
         </p>` : "";
    const scanRows = filteredScans.map(s =>
      `<tr><td>${s.app}</td><td>${s.bundle}</td><td>${s.version}</td><td>${s.build}</td>
       <td>${s.stores.join(", ")}</td><td>${s.verdict.replace(/_/g," ")}</td><td>${s.score}</td>
       <td>${s.crit}</td><td>${s.warn}</td><td>${s.date}</td></tr>`).join("");
    const failRows = filteredFailures.map(f =>
      `<tr><td>${f.cat}</td><td>${f.sev}</td><td>${f.n}×</td><td>${f.pct}%</td></tr>`).join("");

    const html = `<!DOCTYPE html><html><head><title>Reliq Dashboard Summary</title>
<style>
  body{font-family:-apple-system,BlinkMacSystemFont,sans-serif;padding:36px;color:#111;max-width:900px}
  h1{font-size:22px;margin:0 0 4px;letter-spacing:-0.02em}
  h2{font-size:13px;margin:28px 0 8px;text-transform:uppercase;letter-spacing:0.08em;color:#666;border-bottom:1px solid #eee;padding-bottom:6px}
  .meta{font-size:12px;color:#888;margin:0 0 20px}
  .stats{display:flex;gap:16px;margin:16px 0 24px;flex-wrap:wrap}
  .stat{border:1px solid #e5e7eb;border-radius:8px;padding:12px 18px;min-width:130px}
  .stat .lbl{font-size:11px;color:#888;margin-bottom:4px}
  .stat .val{font-size:24px;font-weight:700}
  .stat .unit{font-size:13px;color:#888;margin-left:3px}
  table{width:100%;border-collapse:collapse;font-size:12px}
  th{text-align:left;padding:7px 10px;background:#f9fafb;font-weight:600;color:#374151}
  td{padding:7px 10px;border-top:1px solid #f3f4f6;color:#374151}
  @media print{body{padding:20px}}
</style></head><body>
<h1>Reliq Dashboard Summary</h1>
<p class="meta">Workspace: Zola L. &nbsp;·&nbsp; Exported ${TODAY} &nbsp;·&nbsp; Pro plan · 23/100 scans</p>
${filterNote}
<div class="stats">
  <div class="stat"><div class="lbl">Scans shown</div><div class="val">${metrics.count}<span class="unit">/ 100</span></div></div>
  <div class="stat"><div class="lbl">Pass rate</div><div class="val">${metrics.passRate}<span class="unit">%</span></div></div>
  <div class="stat"><div class="lbl">Avg score</div><div class="val">${metrics.avgScore}<span class="unit">/ 100</span></div></div>
  <div class="stat"><div class="lbl">Top failure</div><div class="val" style="font-size:16px">${metrics.topVal}${metrics.topUnit}</div></div>
</div>
<h2>Recent Scans</h2>
<table><thead><tr><th>App</th><th>Bundle</th><th>Version</th><th>Build</th><th>Stores</th><th>Verdict</th><th>Score</th><th>Critical</th><th>Warnings</th><th>Date</th></tr></thead>
<tbody>${scanRows || "<tr><td colspan='10' style='color:#888;text-align:center;padding:16px'>No scans match active filters.</td></tr>"}</tbody></table>
<h2>Top Failure Types</h2>
<table><thead><tr><th>Category</th><th>Severity</th><th>Count</th><th>% of scans</th></tr></thead>
<tbody>${failRows || "<tr><td colspan='4' style='color:#888;text-align:center;padding:16px'>No failure data.</td></tr>"}</tbody></table>
<script>window.onload=()=>{window.print();}<\/script>
</body></html>`;
    const w = window.open("", "_blank");
    if (w) { w.document.write(html); w.document.close(); }
    else showToast("Pop-up blocked — allow pop-ups and retry", "error");
  };

  const copyDashboardLink = () => {
    const url = window.location.href;
    (navigator.clipboard?.writeText(url) || Promise.reject())
      .catch(() => {
        const el = Object.assign(document.createElement("textarea"), { value:url });
        document.body.appendChild(el); el.select(); document.execCommand("copy"); el.remove();
      });
    showToast("Dashboard link copied");
  };

  const runExport = async (key) => {
    setExportLoading(key);
    setExportOpen(false);
    try {
      await new Promise(r => setTimeout(r, 350));
      if      (key === "pdf")       { exportDashboardPDF();  showToast("PDF ready — check your print dialog"); }
      else if (key === "csv_scans") { exportScansCSV();      showToast("Recent scans CSV downloaded"); }
      else if (key === "json")      { exportScansJSON();     showToast("Recent scans JSON downloaded"); }
      else if (key === "csv_fail")  { exportFailuresCSV();   showToast("Failure types CSV downloaded"); }
      else if (key === "link")      { copyDashboardLink(); }
    } catch (_) {
      showToast("Export failed — try again", "error");
    } finally {
      setExportLoading(null);
    }
  };

  // ── Filter helpers ────────────────────────────────────────────────────────────
  const openFilter = () => {
    setPendingFilters({ ...filters });
    setFilterOpen(f => !f);
    setExportOpen(false);
  };

  const applyFilters = () => {
    setFilters({ ...pendingFilters });
    setFilterOpen(false);
    const n = Object.values(pendingFilters).filter(v => v !== "all").length;
    showToast(n === 0 ? "Filters cleared" : `${n} filter${n !== 1 ? "s" : ""} applied`);
  };

  const resetFilters = () => setPendingFilters(DEFAULT_FILTERS);

  // ── Shared style atoms ────────────────────────────────────────────────────────
  const dropBase = {
    position:"absolute", zIndex:300, top:"calc(100% + 6px)", right:0,
    background:"var(--bg-1)", border:"1px solid var(--line-2)",
    borderRadius:"var(--r-md)",
    boxShadow:"0 8px 28px rgba(0,0,0,0.18), 0 2px 8px rgba(0,0,0,0.10)",
  };
  const menuBtn = {
    display:"flex", alignItems:"center", gap:9, width:"100%",
    padding:"8px 10px", border:"none", background:"transparent",
    borderRadius:6, cursor:"pointer", textAlign:"left",
    fontSize:13, color:"var(--fg-0)", fontFamily:"var(--font-display)",
  };
  const selStyle = {
    width:"100%", background:"var(--bg-2)", border:"1px solid var(--line-2)",
    borderRadius:"var(--r-sm)", padding:"5px 10px",
    fontSize:12.5, color:"var(--fg-0)", outline:"none", cursor:"pointer",
    height:32, boxSizing:"border-box",
  };
  const labelStyle = {
    fontSize:10, fontFamily:"var(--font-mono)", letterSpacing:"0.1em",
    textTransform:"uppercase", color:"var(--fg-3)", marginBottom:5, display:"block",
  };

  // ── Subscription subtitle ────────────────────────────────────────────────────
  const planSub = React.useMemo(() => {
    if (!window.reliqSubscription) return "Team plan · Owner access";

    const sub = window.reliqSubscription;
    const planKey = (sub.getPlan && sub.getPlan()) || "team";
    const cleanPlanKey = String(planKey || "team").toLowerCase();
    const plan =
      (window.PLAN_META && window.PLAN_META[cleanPlanKey] && window.PLAN_META[cleanPlanKey].name) ||
      (cleanPlanKey === "team" ? "Team" : cleanPlanKey.charAt(0).toUpperCase() + cleanPlanKey.slice(1));

    const S = window.RELIQ_USER_STATE;
    const state = sub.getUserState ? sub.getUserState(true) : null;

    if (state === S?.TRIALING) {
      const days = sub.getDaysLeft ? sub.getDaysLeft() : 0;
      return `Trial · ${days} day${days !== 1 ? "s" : ""} left · ${plan} plan`;
    }

    if (state === S?.PAST_DUE) return `${plan} plan · Payment past due`;
    if (state === S?.CANCELED) return `${plan} plan · Subscription canceled`;

    return `${plan} plan · Owner access`;
  }, []);

  // ── Render ────────────────────────────────────────────────────────────────────
  return (
    <AuthLayout
      route="dashboard"
      go={go}
      crumbs={["Workspace", "Dashboard"]}
      actions={
        <button className="btn btn-primary btn-sm" onClick={() => go("/scan/new")}>
          <Icon name="plus" size={13} /> New Scan
        </button>
      }
    >
          <div className="page-head">
            <div>
              <h1 className="page-title">Welcome back, Zola</h1>
              <p className="page-sub">{planSub}</p>
            </div>

            <div style={{display:"flex", gap:8}}>

              {/* ── Export button ───────────────────────────── */}
              <div style={{position:"relative"}} ref={exportWrapRef}>
                <button
                  className="btn btn-sm"
                  disabled={!!exportLoading}
                  onClick={() => { setExportOpen(o => !o); setFilterOpen(false); }}
                  style={{opacity: exportLoading ? 0.7 : 1}}
                >
                  <Icon name="download" size={13} />
                  {exportLoading ? "Exporting…" : "Export"}
                </button>

                {exportOpen && (
                  <div style={{...dropBase, padding:6, minWidth:230}}>
                    {[
                      { key:"pdf",       icon:"file-text", label:"Export dashboard as PDF"  },
                      { key:"csv_scans", icon:"download",  label:"Recent scans — CSV"        },
                      { key:"json",      icon:"code",      label:"Recent scans — JSON"       },
                      { key:"csv_fail",  icon:"sliders",   label:"Failure types — CSV"       },
                    ].map(({ key, icon, label }) => (
                      <button key={key} style={menuBtn} onClick={() => runExport(key)}
                        onMouseEnter={e => e.currentTarget.style.background="var(--bg-3)"}
                        onMouseLeave={e => e.currentTarget.style.background="transparent"}>
                        <Icon name={icon} size={13} style={{color:"var(--fg-3)", flexShrink:0}} />
                        {label}
                      </button>
                    ))}
                    <div style={{height:1, background:"var(--line-1)", margin:"3px 0"}} />
                    <button style={menuBtn} onClick={() => runExport("link")}
                      onMouseEnter={e => e.currentTarget.style.background="var(--bg-3)"}
                      onMouseLeave={e => e.currentTarget.style.background="transparent"}>
                      <Icon name="copy" size={13} style={{color:"var(--fg-3)", flexShrink:0}} />
                      Copy dashboard link
                    </button>
                  </div>
                )}
              </div>

              {/* ── Filter button ───────────────────────────── */}
              <div style={{position:"relative"}} ref={filterWrapRef}>
                <button
                  className={`btn btn-sm${isFiltered ? " btn-primary" : ""}`}
                  onClick={openFilter}
                >
                  <Icon name="sliders" size={13} />
                  {isFiltered ? `Filter · ${activeFilterCount}` : "Filter"}
                </button>

                {filterOpen && (
                  <div style={{...dropBase, minWidth:270, padding:"14px 16px"}}>
                    <div style={{display:"flex", flexDirection:"column", gap:11}}>

                      <div>
                        <span style={labelStyle}>Date range</span>
                        <select value={pendingFilters.dateRange} style={selStyle}
                          onChange={e => setPendingFilters(p => ({...p, dateRange:e.target.value}))}>
                          <option value="all">All time</option>
                          <option value="7d">Last 7 days</option>
                          <option value="30d">Last 30 days</option>
                          <option value="this_month">This month</option>
                          <option value="last_month">Last month</option>
                        </select>
                      </div>

                      <div>
                        <span style={labelStyle}>App</span>
                        <select value={pendingFilters.app} style={selStyle}
                          onChange={e => setPendingFilters(p => ({...p, app:e.target.value}))}>
                          <option value="all">All apps</option>
                          {[...new Set(DASHBOARD_SCANS.map(s => s.app))].map(a =>
                            <option key={a} value={a}>{a}</option>)}
                        </select>
                      </div>

                      <div>
                        <span style={labelStyle}>Platform</span>
                        <select value={pendingFilters.store} style={selStyle}
                          onChange={e => setPendingFilters(p => ({...p, store:e.target.value}))}>
                          <option value="all">All stores</option>
                          <option value="play">Google Play</option>
                          <option value="app">Apple App Store</option>
                          <option value="both">Both stores</option>
                        </select>
                      </div>

                      <div>
                        <span style={labelStyle}>Verdict</span>
                        <select value={pendingFilters.verdict} style={selStyle}
                          onChange={e => setPendingFilters(p => ({...p, verdict:e.target.value}))}>
                          <option value="all">All verdicts</option>
                          <option value="pass">Pass</option>
                          <option value="likely_pass">Likely Pass</option>
                          <option value="needs_fixes">Needs Fixes</option>
                          <option value="will_reject">Will Reject</option>
                        </select>
                      </div>

                      <div>
                        <span style={labelStyle}>Severity</span>
                        <select value={pendingFilters.severity} style={selStyle}
                          onChange={e => setPendingFilters(p => ({...p, severity:e.target.value}))}>
                          <option value="all">All severities</option>
                          <option value="critical">Critical</option>
                          <option value="warning">Warning</option>
                          <option value="info">Info</option>
                        </select>
                      </div>

                      <div>
                        <span style={labelStyle}>Source</span>
                        <select value={pendingFilters.source} style={selStyle}
                          onChange={e => setPendingFilters(p => ({...p, source:e.target.value}))}>
                          <option value="all">All sources</option>
                          <option value="manual">Manual upload</option>
                          <option value="github">GitHub Action</option>
                          <option value="bitrise">Bitrise</option>
                          <option value="eas">EAS build URL</option>
                          <option value="api">API</option>
                        </select>
                      </div>

                    </div>

                    <div style={{display:"flex", gap:8, marginTop:14, paddingTop:12, borderTop:"1px solid var(--line-1)"}}>
                      <button className="btn btn-sm btn-ghost" style={{flex:1}} onClick={resetFilters}>
                        Reset
                      </button>
                      <button className="btn btn-sm btn-primary" style={{flex:2}} onClick={applyFilters}>
                        Apply filters
                      </button>
                    </div>
                  </div>
                )}
              </div>

            </div>
          </div>

          {/* ── Stats grid ─────────────────────────────────── */}
          <div className="stats-grid">
            {stats.map((s, i) => (
              <div className="stat" key={i}>
                <div className="lbl">{s.lbl}</div>
                <div className="val">{s.val}<span className="unit">{s.unit}</span></div>
                <div className={`trend ${s.trend}`}>
                  <Icon name={s.trend === "up" ? "trend-up" : "trend-dn"} size={11} />
                  {s.change}
                </div>
                <Sparkline data={s.spark} color={s.trend === "up" ? "var(--teal)" : "var(--amber)"} />
              </div>
            ))}
          </div>

          <div className="two-col" style={{alignItems:"flex-start"}}>

            {/* ── Recent scans card ───────────────────────── */}
            <div className="card">
              <div className="card-head">
                <div className="card-title">Recent scans</div>
                <span className="chip" style={{marginLeft:"auto"}}>
                  {isFiltered ? `${filteredScans.length} filtered` : "Last 7 days"}
                </span>
                <button className="btn btn-sm btn-ghost" onClick={() => go("/scans")}>
                  View all <Icon name="chevron" size={12} />
                </button>
              </div>

              {filteredScans.length === 0 ? (
                <div style={{padding:"52px 24px", textAlign:"center"}}>
                  <Icon name="search" size={22} style={{color:"var(--fg-3)"}} />
                  <div style={{fontFamily:"var(--font-display)", fontWeight:600, fontSize:14, marginTop:12, color:"var(--fg-2)"}}>
                    No scans match these filters
                  </div>
                  <div style={{fontSize:12.5, color:"var(--fg-3)", marginTop:4}}>
                    Try adjusting or resetting your filters.
                  </div>
                  <button className="btn btn-sm btn-ghost" style={{marginTop:14}}
                    onClick={() => { setFilters(DEFAULT_FILTERS); showToast("Filters cleared"); }}>
                    Reset filters
                  </button>
                </div>
              ) : (
                <table className="tbl">
                  <thead>
                    <tr>
                      <th>App</th>
                      <th>Stores</th>
                      <th>Verdict</th>
                      <th style={{textAlign:"right"}}>Score</th>
                      <th>Issues</th>
                      <th>When</th>
                    </tr>
                  </thead>
                  <tbody>
                    {filteredScans.map(s => (
                      <tr key={s.id} onClick={() => go("/scan/" + s.id)}>
                        <td>
                          <div style={{display:"flex", alignItems:"center", gap:12}}>
                            <AppIcon letters={s.letters} size={32} gradient={s.grad} />
                            <div>
                              <div style={{fontWeight:500, fontSize:13.5}}>{s.app}</div>
                              <div style={{fontFamily:"var(--font-mono)", fontSize:11, color:"var(--fg-3)"}}>
                                {s.version} · build {s.build}
                              </div>
                            </div>
                          </div>
                        </td>
                        <td>
                          <div style={{display:"flex", gap:6}}>
                            {s.stores.map(st => <StoreChip key={st} store={st} iconOnly={true} />)}
                          </div>
                        </td>
                        <td><VerdictPill verdict={s.verdict} /></td>
                        <td style={{textAlign:"right"}}>
                          <span className="mono" style={{
                            fontSize:15, fontWeight:600,
                            color: s.score >= 85 ? "var(--teal)" : s.score >= 60 ? "var(--amber)" : "var(--red)"
                          }}>{s.score}</span>
                          <span className="mono" style={{color:"var(--fg-3)", fontSize:11}}> /100</span>
                        </td>
                        <td>
                          <div style={{display:"flex", gap:8, fontFamily:"var(--font-mono)", fontSize:12}}>
                            {s.crit > 0 && <span style={{color:"var(--red)"}}>● {s.crit}</span>}
                            {s.warn > 0 && <span style={{color:"var(--amber)"}}>● {s.warn}</span>}
                            {s.crit === 0 && s.warn === 0 && <span style={{color:"var(--fg-3)"}}>—</span>}
                          </div>
                        </td>
                        <td style={{fontFamily:"var(--font-mono)", fontSize:12, color:"var(--fg-2)"}}>{s.when}</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              )}
            </div>

            {/* ── Right column ────────────────────────────── */}
            <div style={{display:"flex", flexDirection:"column", gap:16}}>

              {/* Top failure types */}
              <div className="card">
                <div className="card-head">
                  <div className="card-title">Top failure types</div>
                  <span className="card-sub">
                    {isFiltered ? "Filtered view" : "Last 30 days"}
                  </span>
                </div>
                <div className="card-body" style={{padding:"6px 0"}}>
                  {filteredFailures.length === 0 ? (
                    <div style={{padding:"32px 18px", textAlign:"center", color:"var(--fg-3)", fontSize:13}}>
                      No failures match these filters.
                    </div>
                  ) : filteredFailures.map((r, i) => (
                    <div key={i} style={{padding:"10px 18px", borderTop: i===0 ? 0 : "1px solid var(--line-1)"}}>
                      <div style={{display:"flex", alignItems:"center", gap:10, marginBottom:6}}>
                        <Severity level={r.sev} />
                        <span style={{fontSize:13, fontWeight:500}}>{r.cat}</span>
                        <span style={{marginLeft:"auto", fontFamily:"var(--font-mono)", fontSize:12, color:"var(--fg-2)"}}>{r.n}×</span>
                      </div>
                      <div className="bar-track" style={{height:4, background:"var(--bg-3)", borderRadius:2, overflow:"hidden"}}>
                        <div style={{
                          height:"100%", width: r.pct + "%",
                          background: r.sev === "critical" ? "var(--red)" : r.sev === "warning" ? "var(--amber)" : "var(--blue)",
                          boxShadow: `0 0 6px ${r.sev === "critical" ? "var(--red)" : r.sev === "warning" ? "var(--amber)" : "var(--blue)"}`
                        }} />
                      </div>
                    </div>
                  ))}
                </div>
              </div>

              {/* CI/CD CTA — unchanged */}
              <div className="card" style={{
                background:"radial-gradient(120% 80% at 0% 0%, rgba(0,212,170,0.10), transparent 60%), var(--bg-1)",
                borderColor:"rgba(0,212,170,0.25)"
              }}>
                <div className="card-body">
                  <div style={{display:"flex", alignItems:"center", gap:10, marginBottom:10}}>
                    <Icon name="git-branch" size={16} />
                    <span style={{fontFamily:"var(--font-mono)", fontSize:11, letterSpacing:"0.12em", textTransform:"uppercase", color:"var(--teal)"}}>CI/CD</span>
                  </div>
                  <div style={{fontFamily:"var(--font-display)", fontSize:18, fontWeight:600, letterSpacing:"-0.01em", marginBottom:6}}>
                    Run Reliq in your pipeline
                  </div>
                  <p style={{color:"var(--fg-2)", fontSize:13, margin:"0 0 14px"}}>
                    Add the Reliq GitHub Action to fail your CI when critical issues appear. One-line setup.
                  </p>
                  <div className="code-block" style={{marginTop:0, fontSize:11.5}}>
                    <span className="ln">1</span><span className="tag">- uses:</span> <span className="str">reliq/scan@v1</span>{"\n"}
                    <span className="ln">2</span>  <span className="tag">with:</span>{"\n"}
                    <span className="ln">3</span>    <span className="at">api_key:</span> <span className="str">$&#123;&#123; secrets.RELIQ_KEY &#125;&#125;</span>{"\n"}
                    <span className="ln">4</span>    <span className="at">file:</span> <span className="str">./build/app.apk</span>{"\n"}
                    <span className="ln">5</span>    <span className="at">fail_on:</span> <span className="str">critical</span>
                  </div>
                  <div style={{display:"flex", gap:8, marginTop:14}}>
                    <button className="btn btn-sm btn-primary" onClick={() => go("/api")}>Get API key</button>
                    <button className="btn btn-sm" aria-label="View CI/CD documentation"
                      onClick={() => {
                        window.__reliq_pending_focus = { type:"api-tab", tab:"github" };
                        go("/api");
                      }}>
                      <Icon name="external-link" size={12} /> View docs
                    </button>
                  </div>
                </div>
              </div>

            </div>
          </div>
    </AuthLayout>
  );
};

Object.assign(window, { Dashboard, VerdictPill, verdictMeta });
