// Widgets, composable dashboard pieces.
const { Pill, DetBadge, OwnerChip, Sparkbars, Ring, Kpi, AppGlyph, currency } = window;
const { Icons, DATA } = window;

// ---------- WorryItem ----------
function WorryItem({ item, onOpen }) {
  const iconMap = { risk: "Alert", warn: "Warn", info: "Info", ok: "Check" };
  const Ic = Icons[iconMap[item.sev] || "Info"];
  return (
    <div className="worry" onClick={() => onOpen && onOpen(item)}>
      <div className={"icon " + item.sev}><Ic/></div>
      <div className="body">
        <h4>
          <span>{item.title}</span>
          <span className="path">{item.path}</span>
        </h4>
        <div className="detail">{item.detail}</div>
        <div className="actions">
          <button className="btn sm primary" onClick={(e) => { e.stopPropagation(); onOpen && onOpen(item); }}>
            {item.cta} <Icons.Arrow s={12}/>
          </button>
          <button className="btn sm ghost" onClick={(e) => e.stopPropagation()}>Snooze</button>
          <div style={{ marginLeft: "auto", display: "flex", alignItems: "center", gap: 6 }}>
            <span style={{ fontSize: 11.5, color: "var(--muted)" }}>Owner</span>
            <OwnerChip id={item.owner} size={18}/>
            <span style={{ fontSize: 12, color: "var(--ink-3)" }}>{DATA.OPERATORS[item.owner]?.name.split(" ")[0]}</span>
          </div>
        </div>
      </div>
    </div>
  );
}

// ---------- AppTile ----------
function AppTile({ app, onOpen }) {
  const o = DATA.OPERATORS[app.owner];
  const auditColor = app.audit >= 85 ? "ok" : app.audit >= 70 ? "warn" : "risk";
  return (
    <div className="app-tile" onClick={() => onOpen && onOpen(app)}>
      <header>
        <AppGlyph name={app.name} bg={o?.color}/>
        <div style={{ minWidth: 0 }}>
          <div className="name">{app.name}</div>
          <div className="owner">{o?.team} · {app.generator}</div>
        </div>
        <div style={{ marginLeft: "auto" }}>
          <Pill kind={auditColor}>{app.audit}</Pill>
        </div>
      </header>
      <div className="meta">
        {app.flags.length === 0 ? (
          <Pill kind="ok">healthy</Pill>
        ) : (
          app.flags.slice(0,2).map((f,i) =>
            <Pill key={i} kind={f === "shared-key" ? "warn" : f === "deps-stale" ? "warn" : "warn"}>{f.replace("-", " ")}</Pill>
          )
        )}
        <span className="sig">{app.env}</span>
      </div>
      <div className="numbers">
        <div><strong>{app.monthlyUsers}</strong>users</div>
        <div><strong style={{ color: "var(--green)" }}>{app.dauTrend}</strong>30d</div>
      </div>
      <div style={{ fontSize: 11, color: "var(--muted)", display: "flex", gap: 10, justifyContent: "space-between" }}>
        <span>{o?.name} · {o?.team}</span>
        <span>{currency(app.cost)}/mo</span>
      </div>
    </div>
  );
}

// ---------- Pipeline ----------
function Pipeline() {
  const p = DATA.PIPELINE;
  return (
    <div className="pipeline">
      <div className="stage">
        <div className="sname">Pending review</div>
        <div className="sval">{p.pending.count}</div>
        <div className="sfoot">operator-initiated</div>
      </div>
      <div className={"stage gate " + (p.gates.blocked === 0 ? "open" : "blocked")}>
        <span className="gate-badge">Gate</span>
        <div className="sname">In staging</div>
        <div className="sval">{p.staging.count}</div>
        <div className="sfoot">deterministic tests running</div>
      </div>
      <div className={"stage gate " + (p.gates.blocked === 0 ? "open" : "blocked")}>
        <span className="gate-badge">{p.gates.blocked === 0 ? "Open" : p.gates.blocked + " blocked"}</span>
        <div className="sname">Prod gate</div>
        <div className="sval">{p.gates.open}<span style={{ fontSize: 14, color: "var(--muted)" }}> / {p.gates.open + p.gates.blocked}</span></div>
        <div className="sfoot">passing / awaiting approval</div>
      </div>
      <div className="stage">
        <div className="sname">Live</div>
        <div className="sval">{p.prod.count}</div>
        <div className="sfoot">across 7 teams</div>
      </div>
    </div>
  );
}

// ---------- CostBar ----------
function CostBar({ breakdown }) {
  const total = breakdown.compute + breakdown.apis + breakdown.llm;
  const seg = (v, c) => <span style={{ width: `${(v/total)*100}%`, background: c }}/>;
  return (
    <>
      <div className="costbar">
        {seg(breakdown.compute, "var(--ink-3)")}
        {seg(breakdown.apis, "var(--orange)")}
        {seg(breakdown.llm, "var(--amber)")}
      </div>
      <div style={{ display: "flex", gap: 14, fontSize: 11.5, color: "var(--muted)", marginTop: 6 }}>
        <span><span style={{display:"inline-block",width:8,height:8,borderRadius:2,background:"var(--ink-3)",marginRight:5}}/>Compute {currency(breakdown.compute)}</span>
        <span><span style={{display:"inline-block",width:8,height:8,borderRadius:2,background:"var(--orange)",marginRight:5}}/>APIs {currency(breakdown.apis)}</span>
        <span><span style={{display:"inline-block",width:8,height:8,borderRadius:2,background:"var(--amber)",marginRight:5}}/>LLM {currency(breakdown.llm)}</span>
      </div>
    </>
  );
}

// ---------- Connections Graph (drawer) ----------
// App on the left, its resources stacked on the right. Curved edges.
// Replaces the old radial layout that had label overlap with 5+ resources.
function ConnectionsGraph({ app }) {
  const nodes = app.connections || [];
  const rowH = 36;
  const W = 640;
  const padTop = 14;
  const H = Math.max(160, padTop + nodes.length * rowH + padTop);

  const appX = 24, appW = 200;
  const appY = H / 2;
  const resX = 280; // left edge of resources column
  const resW = W - resX - 24;

  const typeIcon = { db: "Database", saas: "Cloud", llm: "Spark", svc: "Gear" };
  const typeLabel = { db: "DB", saas: "SaaS", llm: "LLM", svc: "Svc" };

  const owner = DATA.OPERATORS[app.owner];

  return (
    <div className="card flush" style={{ padding: 0, overflow: "hidden" }}>
      <svg viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="xMidYMid meet" style={{ width: "100%", height: H, display: "block", background: "var(--cream-2)" }}>
        {/* edges */}
        {nodes.map((n, i) => {
          const x1 = appX + appW;
          const y1 = appY;
          const x2 = resX;
          const y2 = padTop + i * rowH + rowH/2;
          const cx1 = x1 + 60, cx2 = x2 - 60;
          return (
            <path key={"e"+i}
              d={`M${x1},${y1} C${cx1},${y1} ${cx2},${y2} ${x2},${y2}`}
              fill="none"
              stroke={n.det === false ? "var(--amber)" : "var(--ink-3)"}
              strokeOpacity={n.det === false ? 0.7 : 0.55}
              strokeWidth="1.4"
              strokeDasharray={n.det === false ? "4 3" : "0"}
            />
          );
        })}

        {/* app card on left */}
        <g>
          <rect x={appX} y={appY - 26} width={appW} height={52} rx={9}
            fill="var(--paper)" stroke="var(--tan-2)" strokeWidth="1"/>
          <circle cx={appX + 16} cy={appY} r={5} fill={owner?.color || "var(--orange)"}/>
          <text x={appX + 28} y={appY - 4} fontSize="12" fill="var(--ink)" fontWeight="600">{app.name}</text>
          <text x={appX + 28} y={appY + 12} fontSize="10.5" fill="var(--muted)">
            {nodes.length} resource{nodes.length === 1 ? "" : "s"} · owner {owner?.initials || "?"}
          </text>
        </g>

        {/* resource rows on right */}
        {nodes.map((n, i) => {
          const y = padTop + i * rowH + rowH/2;
          const Ic = Icons[typeIcon[n.type] || "Cloud"];
          const tagBg = n.type === "db"   ? "var(--cream-3)"
                       : n.type === "llm"  ? "color-mix(in srgb, var(--orange) 12%, var(--paper))"
                       : "var(--paper)";
          return (
            <g key={"n"+i}>
              <rect x={resX} y={y - 14} width={resW} height={28} rx={7}
                fill={tagBg} stroke="var(--tan-2)" strokeWidth="1"/>
              {/* type chip */}
              <rect x={resX + 8} y={y - 8} width={28} height={16} rx={3}
                fill="var(--paper)" stroke="var(--tan-2)" strokeWidth="0.5"/>
              <text x={resX + 22} y={y + 3} fontSize="9" fill="var(--muted)" textAnchor="middle" fontFamily="var(--mono)" letterSpacing="0.06em">
                {typeLabel[n.type] || "API"}
              </text>
              {/* name */}
              <text x={resX + 44} y={y + 4} fontSize="11.5" fill="var(--ink)" fontFamily="var(--mono)">
                {n.name}
              </text>
              {/* det badge on right */}
              {n.det === false ? (
                <g>
                  <rect x={resX + resW - 64} y={y - 8} width={56} height={16} rx={3}
                    fill="var(--amber-bg)" stroke="var(--amber-border)" strokeWidth="0.5"/>
                  <text x={resX + resW - 36} y={y + 3} fontSize="9.5" fill="var(--amber)" textAnchor="middle" fontFamily="var(--mono)">non-det</text>
                </g>
              ) : (
                <g>
                  <rect x={resX + resW - 36} y={y - 8} width={28} height={16} rx={3}
                    fill="var(--green-bg)" stroke="var(--green-border)" strokeWidth="0.5"/>
                  <text x={resX + resW - 22} y={y + 3} fontSize="9.5" fill="var(--green)" textAnchor="middle" fontFamily="var(--mono)">det</text>
                </g>
              )}
            </g>
          );
        })}
      </svg>
    </div>
  );
}

// ---------- Blocked deploys table ----------
function BlockedDeploys({ compact = false, onSelectApp }) {
  const rows = DATA.BLOCKED_DEPLOYS.slice(0, compact ? 3 : 99);
  return (
    <table className="t">
      <thead>
        <tr>
          <th>App</th><th>Version</th><th>Reason</th><th>When</th><th>Owner</th><th>Status</th>
        </tr>
      </thead>
      <tbody>
        {rows.map(r => (
          <tr key={r.id} onClick={() => onSelectApp && onSelectApp(r.app)}>
            <td style={{ fontWeight: 500, color: "var(--ink)" }}>{r.app}</td>
            <td><span className="sig">{r.version}</span></td>
            <td style={{ maxWidth: 360, color: "var(--ink-3)" }}>{r.reason}</td>
            <td style={{ color: "var(--muted)" }}>{r.when}</td>
            <td><OwnerChip id={r.author} size={20}/></td>
            <td>
              {r.status === "held"       && <Pill kind="risk">held</Pill>}
              {r.status === "auto-fixed" && <Pill kind="ok">auto-fixed</Pill>}
              {r.status === "resolved"   && <Pill kind="neutral">resolved</Pill>}
            </td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}

// ---------- Fleet table (CTO) ----------
function FleetTable({ onOpen, apps, groupBy }) {
  const list = apps || DATA.APPS;

  if (groupBy && groupBy !== "none") {
    const buckets = {};
    list.forEach(a => {
      const key = groupBy === "team" ? a.team
                : groupBy === "owner" ? (DATA.OPERATORS[a.owner]?.name || a.owner)
                : groupBy === "generator" ? a.generator
                : groupBy === "env" ? a.env
                : "All";
      (buckets[key] ||= []).push(a);
    });
    const keys = Object.keys(buckets).sort();
    return (
      <table className="t fleet-t">
        <FleetColgroup/>
        <FleetThead/>
        <tbody>
          {keys.map(k => (
            <React.Fragment key={k}>
              <tr className="fleet-group-row">
                <td colSpan={8}>
                  <span className="fleet-group-label">{k}</span>
                  <span className="fleet-group-count">{buckets[k].length} apps</span>
                </td>
              </tr>
              {buckets[k].map(a => <FleetRow key={a.id} app={a} onOpen={onOpen}/>)}
            </React.Fragment>
          ))}
        </tbody>
      </table>
    );
  }

  return (
    <table className="t fleet-t">
      <FleetColgroup/>
      <FleetThead/>
      <tbody>
        {list.map(a => <FleetRow key={a.id} app={a} onOpen={onOpen}/>)}
      </tbody>
    </table>
  );
}

function FleetColgroup() {
  return (
    <colgroup>
      <col style={{ width: "28%" }}/>
      <col style={{ width: "18%" }}/>
      <col style={{ width: "9%" }}/>
      <col style={{ width: "12%" }}/>
      <col style={{ width: "9%" }}/>
      <col style={{ width: "9%" }}/>
      <col style={{ width: "11%" }}/>
      <col style={{ width: "4%" }}/>
    </colgroup>
  );
}

function FleetThead() {
  return (
    <thead>
      <tr>
        <th>App</th><th>Owner / Team</th><th>Audit</th><th>Cost / mo</th>
        <th>Tests</th><th>Deploys</th><th>Flags</th><th></th>
      </tr>
    </thead>
  );
}

function FleetRow({ app: a, onOpen }) {
  const o = DATA.OPERATORS[a.owner];
  return (
    <tr onClick={() => onOpen(a)}>
      <td>
        <div style={{ display: "flex", alignItems: "center", gap: 10, minWidth: 0 }}>
          <AppGlyph name={a.name} bg={o?.color}/>
          <div style={{ minWidth: 0 }}>
            <div style={{ fontWeight: 500, color: "var(--ink)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{a.name}</div>
            <div style={{ fontSize: 11.5, color: "var(--muted)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{a.generator} · {a.lastDeploy}</div>
          </div>
        </div>
      </td>
      <td>
        <div style={{ display: "flex", alignItems: "center", gap: 8, minWidth: 0 }}>
          <OwnerChip id={a.owner} size={22}/>
          <div style={{ minWidth: 0 }}>
            <div style={{ fontSize: 12.5, color: "var(--ink)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{o?.name.split(" ")[0]}</div>
            <div style={{ fontSize: 11, color: "var(--muted)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{a.team}</div>
          </div>
        </div>
      </td>
      <td>
        <Pill kind={a.audit >= 85 ? "ok" : a.audit >= 70 ? "warn" : "risk"}>{a.audit}</Pill>
      </td>
      <td style={{ fontVariantNumeric: "tabular-nums", color: "var(--ink)" }}>{currency(a.cost)}</td>
      <td>
        <span style={{ color: a.tests.passing === a.tests.total ? "var(--green)" : "var(--amber)", fontVariantNumeric: "tabular-nums" }}>
          {a.tests.passing}/{a.tests.total}
        </span>
      </td>
      <td style={{ fontVariantNumeric: "tabular-nums", color: "var(--muted)" }}>{a.deploys7d}</td>
      <td>
        <div style={{ display: "flex", gap: 4, flexWrap: "wrap" }}>
          {a.flags.length === 0 && <Pill kind="ok">ok</Pill>}
          {a.flags.slice(0, 2).map((f, i) => <Pill key={i} kind="warn">{f.replace("-"," ")}</Pill>)}
        </div>
      </td>
      <td style={{ color: "var(--muted)", textAlign: "right" }}><Icons.Arrow/></td>
    </tr>
  );
}

Object.assign(window, { WorryItem, AppTile, Pipeline, CostBar, ConnectionsGraph, BlockedDeploys, FleetTable });
