// Detail drawer, "What does this app touch" view.
const { Pill, DetBadge, OwnerChip, Ring, AppGlyph, Tabs, currency } = window;
const { ConnectionsGraph, CostBar } = window;
const { Icons, DATA } = window;
const { useState } = React;

// Synthetic dependency list per app, stable across renders.
function depsFor(app) {
  const seed = app.id.length + app.depsAge;
  const allDeps = [
    { name: "next",            current: "14.0.4", latest: "14.2.5",  bump: "minor" },
    { name: "react",           current: "18.2.0", latest: "18.3.1",  bump: "patch" },
    { name: "@vercel/ai",      current: "3.0.21", latest: "3.4.10",  bump: "minor" },
    { name: "openai",          current: "4.28.0", latest: "4.52.7",  bump: "minor" },
    { name: "zod",             current: "3.22.4", latest: "3.23.8",  bump: "patch" },
    { name: "stripe",          current: "14.10.0",latest: "15.6.0",  bump: "major" },
    { name: "pg",              current: "8.11.3", latest: "8.12.0",  bump: "patch" },
    { name: "drizzle-orm",     current: "0.29.3", latest: "0.32.1",  bump: "minor" },
    { name: "@aws-sdk/client-s3",current:"3.502.0",latest:"3.609.0", bump: "minor" },
    { name: "snowflake-sdk",   current: "1.9.2",  latest: "1.11.0",  bump: "minor" },
    { name: "axios",           current: "1.6.7",  latest: "1.7.2",   bump: "patch" },
    { name: "date-fns",        current: "3.3.1",  latest: "3.6.0",   bump: "minor" },
  ];
  const count = 8 + (seed % 4);
  const picked = [];
  const seen = new Set();
  for (let i = 0; i < allDeps.length && picked.length < count; i++) {
    const idx = (i * 3 + seed) % allDeps.length;
    if (seen.has(idx)) continue;
    seen.add(idx);
    picked.push(allDeps[idx]);
  }
  // Fill the rest in order if the stride didn't give us enough unique entries.
  for (let i = 0; picked.length < count && i < allDeps.length; i++) {
    if (!seen.has(i)) { seen.add(i); picked.push(allDeps[i]); }
  }
  // Classify: ~60% current, ~25% queued, ~15% in-progress (with a stage).
  const stages = [
    { stage: "in staging",        eta: "deploying May 17" },
    { stage: "operator testing",  eta: "Maya · started 2h ago" },
    { stage: "sandbox tests",     eta: "7 of 12 passed" },
    { stage: "awaiting approval", eta: "queued behind 2 deploys" },
  ];
  return picked.map((d, i) => {
    const slot = (i + seed) % 7;
    if (slot < 4) return { ...d, status: "current" };
    if (slot < 6) return { ...d, status: "queued", eta: ["this week","next sprint","in 3 days","after staging gate"][i % 4] };
    return { ...d, status: "in-progress", ...stages[i % stages.length] };
  });
}

function DepRow({ d }) {
  const bumpKind = d.bump === "major" ? "risk" : d.bump === "minor" ? "warn" : "ok";
  return (
    <tr>
      <td>
        <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
          <span style={{ width: 26, height: 26, borderRadius: 7, background: "var(--cream-3)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--ink-3)" }}>
            <Icons.Box s={13}/>
          </span>
          <span className="sig" style={{ fontSize: 12.5, color: "var(--ink)" }}>{d.name}</span>
        </div>
      </td>
      <td style={{ color: "var(--muted)", fontFamily: "var(--mono)", fontSize: 12 }}>{d.current}</td>
      <td style={{ fontFamily: "var(--mono)", fontSize: 12, color: d.status === "current" ? "var(--muted)" : "var(--ink)" }}>{d.latest}</td>
      <td>
        {d.status === "current"     && <span style={{ color: "var(--muted)", fontSize: 12 }}>-</span>}
        {d.status === "queued"      && <Pill kind={bumpKind}>{d.bump}</Pill>}
        {d.status === "in-progress" && (
          <div style={{ display: "flex", flexDirection: "column", gap: 2 }}>
            <span className="sig" style={{ fontSize: 12, color: "var(--ink)" }}>{d.stage}</span>
            <span style={{ fontSize: 11, color: "var(--muted)" }}>{d.eta}</span>
          </div>
        )}
        {d.status === "queued" && d.eta && (
          <span style={{ marginLeft: 8, fontSize: 11.5, color: "var(--muted)" }}>{d.eta}</span>
        )}
      </td>
    </tr>
  );
}

function AppDetailDrawer({ app, onClose, role, onOpenOutbound, onOpenException, onOpenBudget }) {
  const [tab, setTab] = useState("overview");
  if (!app) return null;
  const o = DATA.OPERATORS[app.owner];
  const deps = depsFor(app);
  const depsCurrent  = deps.filter(d => d.status === "current");
  const depsQueued   = deps.filter(d => d.status === "queued");
  const depsProgress = deps.filter(d => d.status === "in-progress");
  const depsStale    = depsQueued.length + depsProgress.length;

  return (
    <>
      <div className="scrim" onClick={onClose}/>
      <aside className="drawer">
        <div className="drawer-head">
          <div style={{ display: "flex", alignItems: "center", gap: 14 }}>
            <AppGlyph name={app.name} bg={o?.color}/>
            <div>
              <div style={{ fontFamily: "var(--mono)", fontSize: 10.5, color: "var(--muted)", textTransform: "uppercase", letterSpacing: "0.08em" }}>
                {role === "cto" ? "fleet detail" : "my app"} · {app.env}
              </div>
              <h2 style={{ fontFamily: "var(--serif)", fontSize: 28, letterSpacing: "-0.02em", color: "var(--ink)", fontWeight: 400 }}>
                {app.name}
              </h2>
              <div style={{ display: "flex", gap: 10, marginTop: 6, fontSize: 12, color: "var(--muted)", alignItems: "center" }}>
                <span style={{ display: "inline-flex", alignItems: "center", gap: 4 }}>
                  <Icons.User s={11}/>
                  <span style={{ color: "var(--ink-2)", fontWeight: 500 }}>{app.monthlyUsers || app.uniqueMau || 0}</span> monthly users
                </span>
                <span style={{ color: "var(--tan-2)" }}>·</span>
                <a href="#" onClick={(e) => e.preventDefault()} style={{ color: "var(--muted)", textDecoration: "none", display: "inline-flex", alignItems: "center", gap: 4 }}>
                  <Icons.Github s={11}/> meridia/{app.id}
                  <Icons.ExternalLink s={10}/>
                </a>
              </div>
            </div>
          </div>
          <div style={{ display: "flex", gap: 8 }}>
            {role === "cto"
              ? null
              : <button className="btn sm"><Icons.Upload s={12}/> Request approval</button>}
            <button className="btn icon ghost" onClick={onClose}><Icons.X/></button>
          </div>
        </div>

        <div className="drawer-body">
          {/* Summary strip */}
          <div className="grid g-4" style={{ marginBottom: 20 }}>
            <div className="card kpi" style={{ padding: 14 }}>
              <div className="label">Audit</div>
              <div style={{ display: "flex", alignItems: "baseline", gap: 6, marginTop: 4 }}>
                <div style={{ fontFamily: "var(--serif)", fontSize: 30, color: "var(--ink)" }}>{app.audit}</div>
                <Pill kind={app.audit >= 85 ? "ok" : "warn"}>{app.audit >= 85 ? "pass" : "drift"}</Pill>
              </div>
            </div>
            <button type="button" onClick={onOpenBudget} className="card kpi" style={{ padding: 14, textAlign: "left", cursor: "pointer", font: "inherit", color: "inherit" }}>
              <div className="label" style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                <span>Budget</span>
                <Icons.Arrow s={11}/>
              </div>
              <div style={{ display: "flex", alignItems: "baseline", gap: 4, marginTop: 4 }}>
                <div style={{ fontFamily: "var(--serif)", fontSize: 30, color: "var(--ink)" }}>{currency(app.cost)}</div>
                <div style={{ fontSize: 12, color: "var(--muted)" }}>/ {currency(Math.round(app.cost / 0.78 / 100) * 100)}</div>
              </div>
              <div style={{ height: 4, borderRadius: 2, background: "var(--tan-2)", marginTop: 8, overflow: "hidden" }}>
                <div style={{ width: "78%", height: "100%", background: app.cost > 2000 ? "var(--amber)" : "var(--orange)" }}/>
              </div>
            </button>
            <div className="card kpi" style={{ padding: 14 }}>
              <div className="label">Tests</div>
              <div style={{ fontFamily: "var(--serif)", fontSize: 30, color: app.tests.passing === app.tests.total ? "var(--green)" : "var(--amber)", marginTop: 4 }}>
                {app.tests.passing}/{app.tests.total}
              </div>
              {app.tests.failing && app.tests.failing.length > 0 && (
                <div style={{ fontSize: 11.5, color: "var(--amber)", marginTop: 6, lineHeight: 1.35 }}>
                  Failing: <span style={{ color: "var(--ink-2)" }}>{app.tests.failing[0]}</span>
                </div>
              )}
            </div>
            <div className="card kpi" style={{ padding: 14 }}>
              <div className="label">Dependencies</div>
              <div style={{ fontFamily: "var(--serif)", fontSize: 30, color: "var(--ink)", marginTop: 4 }}>{deps.length}</div>
              <div style={{ fontSize: 11.5, color: depsStale > 0 ? "var(--amber)" : "var(--muted)", marginTop: 6, lineHeight: 1.35 }}>
                {depsStale > 0 ? <>{depsStale} updating</> : <>all up to date</>}
              </div>
            </div>
          </div>

          <div style={{ marginBottom: 16 }}>
            <Tabs
              value={tab}
              onChange={setTab}
              items={[
                { value: "overview",     label: "What it touches" },
                { value: "dependencies", label: "Dependencies" },
                { value: "audit",        label: "Governance" },
              ]}
            />
          </div>

          {tab === "overview" && (
            <>
              <div className="card" style={{ marginBottom: 16 }}>
                <div className="card-head">
                  <div>
                    <h3>Outbound connections</h3>
                    <div className="subtitle">Every internal resource and external service this app touches.</div>
                  </div>
                  <div className="legend">
                    <span><span className="sw" style={{ background: "var(--green)" }}/>deterministic</span>
                    <span><span className="sw" style={{ background: "var(--amber)" }}/>non-deterministic</span>
                  </div>
                </div>
                <ConnectionsGraph app={app}/>
              </div>

              <div className="card flush">
                <table className="t">
                  <thead>
                    <tr><th>Resource</th><th>Type</th><th>Policy</th><th>Last call</th><th></th></tr>
                  </thead>
                  <tbody>
                    {app.connections.map((c, i) => {
                      const typeLabel = { db: "Data", saas: "API", llm: "LLM", svc: "API" }[c.type] || c.type.toUpperCase();
                      const Ic = Icons[{ db: "Database", saas: "Cloud", llm: "Spark", svc: "Gear" }[c.type] || "Cloud"];
                      // Synthetic policy state. Most allowlisted; one denied; one first-seen.
                      const polSeed = (app.id.length + c.name.length + i) % 9;
                      const policy = polSeed === 3 ? "denied" : polSeed === 5 ? "first-seen" : "allowlist";
                      const polCfg = {
                        allowlist:   { label: "Allowlisted",       kind: "ok"   },
                        denied:      { label: "Denied",            kind: "risk" },
                        "first-seen":{ label: "First seen 4d ago", kind: "warn" },
                      }[policy];
                      let ctaLabel = null, ctaHandler = null;
                      if (policy === "denied")     { ctaLabel = "Request allowlist"; ctaHandler = onOpenOutbound; }
                      if (policy === "first-seen") { ctaLabel = "Request allowlist"; ctaHandler = onOpenOutbound; }
                      return (
                        <tr key={i}>
                          <td>
                            <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                              <span style={{ width: 26, height: 26, borderRadius: 7, background: "var(--cream-3)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--ink-3)" }}>
                                <Ic s={13}/>
                              </span>
                              <span className="sig" style={{ fontSize: 12.5, color: "var(--ink)" }}>{c.name}</span>
                            </div>
                          </td>
                          <td style={{ color: "var(--muted)", fontFamily: "var(--mono)", fontSize: 11.5, textTransform: "uppercase", letterSpacing: "0.06em" }}>{typeLabel}</td>
                          <td><Pill kind={polCfg.kind}>{polCfg.label}</Pill></td>
                          <td style={{ color: "var(--muted)" }}>{["3m","12m","1h","2h","6h","1d"][i % 6]} ago</td>
                          <td>{ctaLabel ? <button className="btn ghost sm" onClick={ctaHandler}>{ctaLabel} <Icons.Arrow s={11}/></button> : null}</td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              </div>

              <div className="card" style={{ marginTop: 16 }}>
                <div className="card-head">
                  <div>
                    <h3>Stack</h3>
                    <div className="subtitle">Generated with <span className="sig">{app.generator}</span></div>
                  </div>
                </div>
                <div style={{ display: "flex", gap: 6, flexWrap: "wrap" }}>
                  {app.stack.map((s, i) => <Pill key={i} kind="neutral">{s}</Pill>)}
                </div>
              </div>
            </>
          )}

          {tab === "dependencies" && (
            <>
              <div className="card" style={{ marginBottom: 16 }}>
                <div style={{ fontFamily: "var(--mono)", fontSize: 10.5, color: "var(--muted)", textTransform: "uppercase", letterSpacing: "0.08em" }}>Dependency status</div>
                <h3 style={{ fontFamily: "var(--serif)", fontSize: 22, letterSpacing: "-0.02em", fontWeight: 400, marginTop: 4 }}>
                  {depsStale === 0
                    ? "All dependencies current"
                    : <>{depsCurrent.length} current · {depsQueued.length} queued · {depsProgress.length} in progress</>}
                </h3>
                <div style={{ color: "var(--muted)", fontSize: 13, marginTop: 6, maxWidth: 520 }}>
                  {app.owner ? `${DATA.OPERATORS[app.owner]?.name?.split(" ")[0] || "The operator"} owns updates for this app.` : ""} Stoda runs the deterministic test suite against each upgrade in an ephemeral sandbox before staging.
                </div>
              </div>

              {depsProgress.length > 0 && (
                <div className="card flush" style={{ marginBottom: 16 }}>
                  <div style={{ padding: "12px 16px", borderBottom: "1px solid var(--tan-2)", display: "flex", alignItems: "center", gap: 8 }}>
                    <span style={{ width: 8, height: 8, borderRadius: "50%", background: "var(--orange)" }}/>
                    <h3 style={{ margin: 0, fontFamily: "var(--serif)", fontSize: 16, fontWeight: 500 }}>In progress</h3>
                    <span style={{ marginLeft: "auto", color: "var(--muted)", fontSize: 12 }}>{depsProgress.length} package{depsProgress.length === 1 ? "" : "s"}</span>
                  </div>
                  <table className="t">
                    <thead><tr><th>Package</th><th>From</th><th>To</th><th>Stage</th></tr></thead>
                    <tbody>{depsProgress.map((d, i) => <DepRow key={i} d={d}/>)}</tbody>
                  </table>
                </div>
              )}

              {depsQueued.length > 0 && (
                <div className="card flush" style={{ marginBottom: 16 }}>
                  <div style={{ padding: "12px 16px", borderBottom: "1px solid var(--tan-2)", display: "flex", alignItems: "center", gap: 8 }}>
                    <span style={{ width: 8, height: 8, borderRadius: "50%", background: "var(--amber)" }}/>
                    <h3 style={{ margin: 0, fontFamily: "var(--serif)", fontSize: 16, fontWeight: 500 }}>Update queued</h3>
                    <span style={{ marginLeft: "auto", color: "var(--muted)", fontSize: 12 }}>{depsQueued.length} package{depsQueued.length === 1 ? "" : "s"}</span>
                  </div>
                  <table className="t">
                    <thead><tr><th>Package</th><th>Current</th><th>Latest</th><th>Bump · ETA</th></tr></thead>
                    <tbody>{depsQueued.map((d, i) => <DepRow key={i} d={d}/>)}</tbody>
                  </table>
                </div>
              )}

              {depsCurrent.length > 0 && (
                <div className="card flush">
                  <div style={{ padding: "12px 16px", borderBottom: "1px solid var(--tan-2)", display: "flex", alignItems: "center", gap: 8 }}>
                    <span style={{ width: 8, height: 8, borderRadius: "50%", background: "var(--green)" }}/>
                    <h3 style={{ margin: 0, fontFamily: "var(--serif)", fontSize: 16, fontWeight: 500 }}>Up to date</h3>
                    <span style={{ marginLeft: "auto", color: "var(--muted)", fontSize: 12 }}>{depsCurrent.length} package{depsCurrent.length === 1 ? "" : "s"}</span>
                  </div>
                  <table className="t">
                    <thead><tr><th>Package</th><th>Current</th><th>Latest</th><th></th></tr></thead>
                    <tbody>{depsCurrent.map((d, i) => <DepRow key={i} d={d}/>)}</tbody>
                  </table>
                </div>
              )}
            </>
          )}

          {tab === "audit" && (
            <>
              <div className="card" style={{ marginBottom: 16, display: "flex", gap: 20, alignItems: "center" }}>
                <Ring value={app.audit} label="Audit"/>
                <div style={{ flex: 1 }}>
                  {app.audit >= 85 ? (
                    <>
                      <h3 style={{ fontFamily: "var(--serif)", fontSize: 22, letterSpacing: "-0.02em", fontWeight: 400 }}>
                        Ready for audit
                      </h3>
                      <div style={{ color: "var(--muted)", fontSize: 13, marginTop: 4 }}>
                        Deterministic rules produce a signed, re-runnable verdict. Last scan 38 minutes ago.
                      </div>
                      <div style={{ display: "flex", gap: 8, marginTop: 12 }}>
                        <button className="btn primary sm"><Icons.Flask s={12}/> Re-run scan</button>
                      </div>
                    </>
                  ) : (
                    <>
                      <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 4 }}>
                        <span style={{ width: 8, height: 8, borderRadius: 999, background: "var(--amber)", display: "inline-block" }}/>
                        <span className="eyebrow" style={{ color: "var(--amber)" }}>Deployment held in staging</span>
                      </div>
                      <h3 style={{ fontFamily: "var(--serif)", fontSize: 22, letterSpacing: "-0.02em", fontWeight: 400 }}>
                        Operator flagged · pending resolution
                      </h3>
                      <div style={{ color: "var(--muted)", fontSize: 13, marginTop: 4, lineHeight: 1.55 }}>
                        Stoda paused promotion to production 38 min ago after {app.flags.includes("shared-key") ? "the per-app key rule" : "two rules"} flipped. The build sits in staging until the operator resolves it, or you override.
                      </div>
                      <div style={{ display: "flex", gap: 8, marginTop: 12 }}>
                        <button className="btn sm">Override &amp; deploy <Icons.Arrow s={12}/></button>
                      </div>
                    </>
                  )}
                </div>
              </div>

              <div className="card flush">
                <table className="t">
                  <thead><tr><th>Rule</th><th>Verdict</th><th>Last verified</th></tr></thead>
                  <tbody>
                    {[
                      { r: "All outbound domains on allowlist",           v: "pass" },
                      { r: "No secrets in code",                          v: "pass" },
                      { r: "Per-app key isolation",                       v: app.flags.includes("shared-key") ? "fail" : "pass" },
                      { r: "Dependencies ≤ 30 days stale",                v: app.depsAge > 30 ? "fail" : "pass" },
                      { r: "Deterministic tests cover happy path",        v: app.tests.passing === app.tests.total ? "pass" : "fail" },
                      { r: "Non-det LLM calls schema-pinned",             v: app.audit >= 85 ? "pass" : "warn" },
                      { r: "Backup restore tested in last 90 days",       v: "pass" },
                      { r: "Staging gate enforced",                       v: "pass" },
                    ].map((r, i) => (
                      <tr key={i}>
                        <td>{r.r}</td>
                        <td>
                          {r.v === "pass" && <Pill kind="ok">pass</Pill>}
                          {r.v === "warn" && <Pill kind="warn">drift</Pill>}
                          {r.v === "fail" && <Pill kind="risk">fail</Pill>}
                        </td>
                        <td style={{ color: "var(--muted)" }}>38m ago</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            </>
          )}
        </div>
      </aside>
    </>
  );
}

window.AppDetailDrawer = AppDetailDrawer;
