/* Voyage Fleet — Drift Report. Exports: DriftReport. */

const { useState: useS_dr, useMemo: useMemo_dr } = React;

/* ════════════ DRIFT REPORT ════════════ */
function DriftBar({ label, segments, total }) {
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 10 }}>
      <span style={{ width: 80, fontSize: 12.5, color: "var(--jrni-color-text-soft)", textAlign: "right", flexShrink: 0 }}>{label}</span>
      <div style={{ flex: 1, display: "flex", height: 26, borderRadius: 5, overflow: "hidden", background: "var(--jrni-color-neutral-6)" }}>
        {segments.map((s, i) => s.count > 0 ? (
          <div key={i} title={`${s.label}: ${s.count}`} style={{ width: `${(s.count / total) * 100}%`, background: s.color, display: "flex", alignItems: "center", justifyContent: "center", color: "white", fontSize: 11, fontWeight: 700, minWidth: s.count > 0 ? 18 : 0 }}>{s.count > 1 ? s.count : ""}</div>
        ) : null)}
      </div>
    </div>
  );
}

function DriftReport({ params }) {
  const [selected, setSelected] = useS_dr(new Set());
  const F = window.FLEET;
  const rows = useMemo_dr(() => {
    const ind = params.industry ? params.industry.split(",").filter(Boolean) : [];
    const envs = params.env ? params.env.split(",").filter(Boolean) : [];
    return [...F.TENANTS]
      .sort((a, b) => ({ none: 0, patch: 1, minor: 2, major: 3 }[b.drift]) - ({ none: 0, patch: 1, minor: 2, major: 3 }[a.drift]))
      .filter(t => t.drift !== "none")
      .filter(t => !ind.length || ind.includes(t.industry))
      .filter(t => !envs.length || envs.includes(t.env))
      .filter(t => params.revWindow !== "lt7" || t.lastRevDays < 7)
      .filter(t => params.revWindow !== "7to30" || (t.lastRevDays >= 7 && t.lastRevDays <= 30))
      .filter(t => params.revWindow !== "gt30" || t.lastRevDays > 30);
  }, [F.size, params.industry, params.env, params.revWindow]);
  const driftColors = { none: "var(--jrni-color-semantic-green-1)", patch: "var(--jrni-color-semantic-blue-1)", minor: "var(--jrni-color-semantic-orange-1)", major: "var(--jrni-color-semantic-red-1)" };
  const byEnv = env => ["none", "patch", "minor", "major"].map(d => ({ label: d, color: driftColors[d], count: F.TENANTS.filter(t => t.env === env && t.drift === d).length }));

  const toggle = slug => setSelected(s => { const n = new Set(s); n.has(slug) ? n.delete(slug) : n.add(slug); return n; });
  const toggleAll = () => setSelected(s => { const all = rows.every(r => s.has(r.slug)); const n = new Set(s); rows.forEach(r => all ? n.delete(r.slug) : n.add(r.slug)); return n; });
  const booting = useBoot(params);

  const extraCols = [
    { key: "commitsBehind", label: "Behind", w: 70, render: t => <span style={{ fontSize: 12.5, color: "var(--jrni-color-neutral-1)", fontFamily: "var(--jrni-font-family-mono)" }}>{t.commitsBehind}</span> },
    { key: "outMinor", label: "Outdated", w: 110, render: t => <span style={{ display: "inline-flex", gap: 5 }}>{t.modulesOutdatedMinor ? <Pill tone="warning">{t.modulesOutdatedMinor} minor</Pill> : null}{t.modulesOutdatedMajor ? <Pill tone="danger">{t.modulesOutdatedMajor} major</Pill> : null}</span> },
    { key: "effort", label: "Effort", w: 90, render: t => <Pill tone={t.effort === "large" ? "danger" : t.effort === "medium" ? "warning" : "success"}>{t.effort}</Pill> },
    { key: "lastActor", label: "Last action", w: 130, render: t => <ActorChip name={t.lastActor} isBot={["GitHub Actions","auto-merge bot"].includes(t.lastActor)} size="sm" /> },
  ];

  return (
    <div style={{ display: "flex", minHeight: 0, flex: 1 }}>
      <div style={{ flex: 1, minWidth: 0, overflowY: "auto", padding: "20px 24px 28px", display: "flex", flexDirection: "column", gap: 16 }}>
        <div>
          <h1 style={{ margin: 0, fontSize: 22, fontWeight: 700, color: "var(--jrni-color-neutral-1)", letterSpacing: -0.3 }}>Drift Report</h1>
          <p style={{ margin: "3px 0 0", fontSize: 13.5, color: "var(--jrni-color-text-soft)" }}>{rows.length} tenants behind on at least one component. Weekly audit ran 3h ago.</p>
        </div>

        <Card padding={18}>
          <SectionLabel>Drift distribution by environment</SectionLabel>
          {booting ? <div style={{ marginTop: 12 }}><Skeleton w="100%" h={26} r={5} style={{ marginBottom: 10 }} /><Skeleton w="100%" h={26} r={5} /></div> : (
          <React.Fragment>
          <div style={{ marginTop: 12 }}>
            <DriftBar label="Production" segments={byEnv("prod")} total={F.TENANTS.filter(t => t.env === "prod").length} />
            <DriftBar label="Development" segments={byEnv("dev")} total={F.TENANTS.filter(t => t.env === "dev").length} />
          </div>
          <div style={{ display: "flex", gap: 16, marginTop: 10, flexWrap: "wrap" }}>
            {[["Up to date", "none"], ["Patch behind", "patch"], ["Minor behind", "minor"], ["Major behind", "major"]].map(l => (
              <span key={l[1]} style={{ display: "inline-flex", alignItems: "center", gap: 6, fontSize: 12, color: "var(--jrni-color-text-soft)" }}><span style={{ width: 9, height: 9, borderRadius: 2, background: driftColors[l[1]] }} />{l[0]} · <b style={{ color: "var(--jrni-color-neutral-1)" }}>{F.countDrift(l[1])}</b></span>
            ))}
          </div>
          </React.Fragment>
          )}
        </Card>

        <div style={{ display: "flex", gap: 8, flexWrap: "wrap", alignItems: "center" }}>
          <MultiFilter label="Industry" value={params.industry} onChange={v => setParam({ industry: v })} options={F.INDUSTRIES.map(i => ({ value: i, label: i }))} />
          <MultiFilter label="Environment" value={params.env} onChange={v => setParam({ env: v })} options={[{ value: "prod", label: "Production" }, { value: "dev", label: "Development" }]} />
          <SingleFilter label="Time since last rev" value={params.revWindow} onChange={v => setParam({ revWindow: v })} options={[{ value: "any", label: "Any" }, { value: "lt7", label: "< 7 days" }, { value: "7to30", label: "7–30 days" }, { value: "gt30", label: "> 30 days" }]} />
          {(params.industry || params.env || params.revWindow) ? <button onClick={() => navigate("/drift", {})} style={{ height: 32, padding: "0 10px", borderRadius: 6, border: "none", background: "transparent", color: "var(--jrni-color-primary-1)", fontSize: 12.5, fontWeight: 600, cursor: "pointer", fontFamily: "var(--jrni-font-family-sans)" }}>Clear</button> : null}
          <span style={{ marginLeft: "auto", fontSize: 12.5, color: "var(--jrni-color-text-soft)" }}><b style={{ color: "var(--jrni-color-neutral-1)" }}>{rows.length}</b> tenants</span>
        </div>

        {selected.size > 0 ? (
          <div style={{ display: "flex", alignItems: "center", gap: 12, padding: "8px 14px", background: "var(--jrni-color-primary-4)", border: "1px solid var(--jrni-color-primary-2)", borderRadius: 8 }}>
            <span style={{ fontSize: 13, fontWeight: 600, color: "var(--jrni-color-primary-1)" }}>{selected.size} selected</span>
            <Button variant="primary" size="sm" icon={<Icons.Bolt size={12} />} onClick={() => navigate("/bulk", { from: "drift" })}>Plan component rev</Button>
            <Button variant="secondary" size="sm" icon={<Icons.GitPr size={12} />}>Open upgrade PRs</Button>
            <span style={{ fontSize: 11.5, color: "var(--jrni-color-text-soft)", display: "inline-flex", alignItems: "center", gap: 5 }}><Icons.Terminal size={12} />Revs run in Claude Code</span>
            <button onClick={() => setSelected(new Set())} style={{ marginLeft: "auto", background: "none", border: "none", cursor: "pointer", color: "var(--jrni-color-primary-1)", fontSize: 12.5, fontWeight: 600 }}>Clear</button>
          </div>
        ) : null}

        {booting ? (
          <div style={{ border: "1px solid var(--jrni-color-surface-border)", borderRadius: 8, background: "white", overflow: "hidden" }}><SkeletonRows n={8} /></div>
        ) : rows.length === 0 ? (
          <div style={{ padding: "40px 24px", textAlign: "center", border: "1px dashed var(--jrni-color-surface-border-strong)", borderRadius: 8, background: "var(--jrni-color-surface-card-soft)" }}>
            <span style={{ width: 52, height: 52, borderRadius: 999, background: "var(--jrni-color-status-success-bg)", color: "var(--jrni-color-semantic-green-1)", display: "grid", placeItems: "center", margin: "0 auto 12px" }}><Icons.Check size={26} /></span>
            <h3 style={{ margin: "0 0 4px", fontSize: 16, fontWeight: 700, color: "var(--jrni-color-neutral-1)" }}>No drift — every tenant is current 🎉</h3>
            <p style={{ margin: 0, fontSize: 13.5, color: "var(--jrni-color-text-soft)" }}>Every tenant's components are at their latest published versions. Nothing to upgrade.</p>
          </div>
        ) : (
          <FleetTable rows={rows} selected={selected} onToggleSelect={toggle} onToggleAll={toggleAll} extraCols={extraCols} dense />
        )}
      </div>

      <div style={{ width: 296, flexShrink: 0, borderLeft: "1px solid var(--jrni-color-surface-border)", background: "white", padding: 18, overflowY: "auto" }}>
        <SectionLabel>Recently published components</SectionLabel>
        <div style={{ marginTop: 8, display: "flex", flexDirection: "column", gap: 0 }}>
          {F.COMPONENT_RELEASES.filter(r => r.latest).slice(0, 6).map((r, i, arr) => (
            <div key={r.module} style={{ padding: "9px 0", borderBottom: i < arr.length - 1 ? "1px solid var(--jrni-color-surface-border)" : "none" }}>
              <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                <span style={{ fontSize: 12.5, fontWeight: 600, color: "var(--jrni-color-neutral-1)" }}>{r.display}</span>
                <VersionChip version={r.version} drift="none" />
                <span style={{ marginLeft: "auto", fontSize: 11, color: "var(--jrni-color-text-soft)" }}>{r.date}</span>
              </div>
              <div style={{ fontSize: 12, color: "var(--jrni-color-text-soft)", marginTop: 4 }}>{r.note}{r.migrations ? ` · ${r.migrations} migration${r.migrations > 1 ? "s" : ""}` : ""}</div>
            </div>
          ))}
        </div>
        <div style={{ marginTop: 14 }}><Button variant="secondary" size="sm" fullWidth icon={<Icons.Release size={13} />} onClick={() => navigate("/releases")}>Open Component Releases</Button></div>
        <div style={{ height: 1, background: "var(--jrni-color-surface-border)", margin: "18px 0" }} />
        <SectionLabel>How drift is computed</SectionLabel>
        <div style={{ fontSize: 12, color: "var(--jrni-color-text-soft)", lineHeight: 1.5, marginTop: 6 }}>Drift is per-component: each pinned <Mono>@voyage/*</Mono> version is compared to that component's latest publish. A tenant's severity is the worst of its components.</div>
      </div>
    </div>
  );
}

window.DriftReport = DriftReport;
