/* Sentinel — Change tracker / registry + Audit trail. */

const STATE_MAP = {
  proposed:     { label: "Proposed",     tone: "info" },
  accepted:     { label: "Accepted",     tone: "success" },
  edited:       { label: "Edited",       tone: "warning" },
  rejected:     { label: "Rejected",     tone: "danger" },
  renegotiated: { label: "Renegotiated", tone: "progress" },
};

const STATE_FILTERS = ["All", "proposed", "accepted", "edited", "rejected", "renegotiated"];

function VariationRow({ r }) {
  const st = STATE_MAP[r.state];
  const reneg = r.state === "renegotiated";
  const accepted = r.state === "accepted" || r.state === "edited";
  return (
    <div style={{ display: "grid", gridTemplateColumns: "168px 1fr 1fr 132px", gap: 14, padding: "12px 16px", alignItems: "start",
      borderTop: "1px solid var(--border-subtle)", borderLeft: reneg ? "3px solid var(--status-warning)" : accepted ? "3px solid var(--status-success)" : "3px solid transparent",
      background: reneg ? "var(--warning-50)" : "transparent" }}>
      <div style={{ minWidth: 0 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 8 }}><Avatar name={r.provider} size={24} tone="neutral" />
          <span style={{ fontSize: 13, fontWeight: 500, color: "var(--content-strong)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{r.provider}</span></div>
        <div style={{ fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--content-faint)", marginTop: 3 }}>{r.contract} · {r.type} · R{r.round}</div>
      </div>
      <div style={{ fontSize: 12.5, color: "var(--content-muted)", lineHeight: 1.45 }}>
        <span className="text-label" style={{ display: "block", marginBottom: 2 }}>Provider asked</span>{r.providerAsk}</div>
      <div style={{ fontSize: 12.5, color: accepted ? "var(--status-success)" : "var(--content-base)", lineHeight: 1.45 }}>
        <span className="text-label" style={{ display: "block", marginBottom: 2 }}>{r.final ? "Outcome" : "Our position"}</span>
        <span style={{ display: "inline-flex", gap: 5 }}>{accepted && <Icon name="check" size={13} style={{ marginTop: 2, flex: "none" }} />}<span>{r.final || r.ourCounter}</span></span></div>
      <div style={{ textAlign: "right" }}>
        <StatusBadge tone={st.tone}>{reneg && <Icon name="flag" size={11} />}{st.label}</StatusBadge>
        <div style={{ fontSize: 11, color: "var(--content-faint)", marginTop: 5 }}>{r.decidedBy !== "—" ? r.decidedBy : "Awaiting"}</div>
        <div style={{ fontSize: 11, color: "var(--content-faint)" }}>{r.date}</div>
      </div>
    </div>
  );
}

function ClauseGroup({ ckey, rows }) {
  const ctx = React.useContext(SentinelCtx);
  const [open, setOpen] = React.useState(true);
  const cl = CLAUSES[ckey];
  const counts = rows.reduce((a, r) => { a[r.state] = (a[r.state] || 0) + 1; return a; }, {});
  const reneg = counts.renegotiated || 0, acc = (counts.accepted || 0) + (counts.edited || 0), open_ = counts.proposed || 0;
  return (
    <Card style={{ overflow: "hidden", marginBottom: 12 }}>
      <button onClick={() => setOpen((o) => !o)} style={{ display: "flex", alignItems: "center", gap: 12, width: "100%", padding: "14px 18px", border: "none",
        background: "var(--bg-surface)", cursor: "pointer", fontFamily: "var(--font-body)", textAlign: "left" }}
        onMouseEnter={(e) => (e.currentTarget.style.background = "var(--bg-sunken)")} onMouseLeave={(e) => (e.currentTarget.style.background = "var(--bg-surface)")}>
        <RiskBadge risk={cl.risk} style={ctx.riskStyle} size="sm" />
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 9 }}>
            <span style={{ fontSize: 15, fontWeight: 600, color: "var(--content-strong)" }}>{cl.title}</span>
            <span style={{ fontFamily: "var(--font-mono)", fontSize: 11.5, color: "var(--content-base)", background: "var(--bg-sunken)", border: "1px solid var(--border-base)", borderRadius: 4, padding: "1px 6px" }}>Std. {STD_CLAUSE[ckey]}</span>
            {cl.protected && <span style={{ display: "inline-flex", alignItems: "center", gap: 3, fontSize: 11, fontWeight: 600, color: "var(--content-muted)" }}><Icon name="lock" size={11} />Protected</span>}
          </div>
          <div style={{ fontSize: 12.5, color: "var(--content-muted)", marginTop: 2 }}>{rows.length} provider variation{rows.length !== 1 ? "s" : ""} across rounds</div>
        </div>
        <div style={{ display: "flex", gap: 7, alignItems: "center" }}>
          {acc > 0 && <span style={{ display: "inline-flex", alignItems: "center", gap: 4, fontSize: 12, color: "var(--status-success)", fontWeight: 600 }}><Icon name="check-circle-2" size={13} />{acc} accepted</span>}
          {reneg > 0 && <span style={{ display: "inline-flex", alignItems: "center", gap: 4, fontSize: 12, color: "var(--status-warning)", fontWeight: 600 }}><Icon name="flag" size={13} />{reneg} renegotiated</span>}
          {open_ > 0 && <span style={{ display: "inline-flex", alignItems: "center", gap: 4, fontSize: 12, color: "var(--status-info)", fontWeight: 600 }}><Icon name="circle-dot" size={13} />{open_} open</span>}
        </div>
        <Icon name={open ? "chevron-up" : "chevron-down"} size={18} style={{ color: "var(--content-muted)", marginLeft: 4 }} />
      </button>
      {open && <div style={{ background: "var(--bg-page)" }}>{rows.slice().sort((a, b) => b.round - a.round).map((r) => <VariationRow key={r.id} r={r} />)}</div>}
    </Card>
  );
}

function Tracker({ search }) {
  const [risk, setRisk] = React.useState("All");
  const [state, setState] = React.useState("All");
  const [view, setView] = React.useState("clause");
  const ctx = React.useContext(SentinelCtx);
  let rows = REGISTRY.filter((r) => {
    const q = (search || "").trim().toLowerCase();
    const okQ = !q || [r.clause, r.provider, r.contract, r.type].join(" ").toLowerCase().includes(q);
    const okR = risk === "All" || r.clauseRisk === risk;
    const okS = state === "All" || r.state === state;
    return okQ && okR && okS;
  });
  // group by clauseKey, preserve clause order from CLAUSES, sort by variation count
  const groups = {};
  rows.forEach((r) => { (groups[r.clauseKey] = groups[r.clauseKey] || []).push(r); });
  const groupKeys = Object.keys(groups).sort((a, b) => groups[b].length - groups[a].length || RISK[CLAUSES[b].risk].sev - RISK[CLAUSES[a].risk].sev);

  return (
    <div style={{ padding: 24 }}>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr 1fr", gap: 14, marginBottom: 18 }}>
        <KpiCard label="Clauses logged" value={REGISTRY.length} icon="library" sub="across 8 providers" subTone="muted" />
        <KpiCard label="Renegotiation rate" value="14%" icon="git-branch" sub="re-opened in a later round" subTone="muted" />
        <KpiCard label="Redline accept rate" value="78%" icon="check-check" sub="counters accepted unedited" subTone="success" />
        <KpiCard label="Battleground clauses" value={Object.keys(groups).length} icon="swords" sub="distinct standard clauses" subTone="muted" />
      </div>

      <div style={{ display: "flex", gap: 8, marginBottom: 14, alignItems: "center", flexWrap: "wrap" }}>
        <div style={{ display: "inline-flex", background: "var(--bg-sunken)", borderRadius: "var(--radius-full)", padding: 3, gap: 2, marginRight: 6 }}>
          {[["clause", "By clause", "layers"], ["flat", "By change", "list"]].map(([v, lbl, ic]) => (
            <button key={v} onClick={() => setView(v)} style={{ display: "inline-flex", alignItems: "center", gap: 5, padding: "5px 12px", borderRadius: "var(--radius-full)", border: "none", cursor: "pointer",
              fontFamily: "var(--font-body)", fontSize: 12.5, fontWeight: 600, background: view === v ? "var(--bg-surface)" : "transparent", color: view === v ? "var(--content-strong)" : "var(--content-muted)", boxShadow: view === v ? "var(--elev-1)" : "none" }}><Icon name={ic} size={13} />{lbl}</button>
          ))}
        </div>
        <span className="text-label" style={{ marginRight: 2 }}>Risk</span>
        {["All", ...RISK_ORDER].map((rk) => (
          <button key={rk} onClick={() => setRisk(rk)} style={{ fontFamily: "var(--font-body)", fontSize: 12.5, fontWeight: 500, padding: "5px 11px", borderRadius: "var(--radius-full)", cursor: "pointer",
            border: `1px solid ${risk === rk ? "var(--ec-primary)" : "var(--border-base)"}`, background: risk === rk ? "var(--green-50)" : "var(--bg-surface)", color: risk === rk ? "var(--green-800)" : "var(--content-base)" }}>{rk === "All" ? "All" : RISK[rk].short}</button>
        ))}
        <span style={{ width: 1, height: 20, background: "var(--border-base)", margin: "0 4px" }} />
        <span className="text-label" style={{ marginRight: 2 }}>State</span>
        {STATE_FILTERS.map((s) => (
          <button key={s} onClick={() => setState(s)} style={{ fontFamily: "var(--font-body)", fontSize: 12.5, fontWeight: 500, padding: "5px 11px", borderRadius: "var(--radius-full)", cursor: "pointer",
            border: `1px solid ${state === s ? "var(--ec-primary)" : "var(--border-base)"}`, background: state === s ? "var(--green-50)" : "var(--bg-surface)", color: state === s ? "var(--green-800)" : "var(--content-base)" }}>{s === "All" ? "All" : STATE_MAP[s].label}</button>
        ))}
        <div style={{ marginLeft: "auto" }}><Button variant="secondary" size="sm" leadingIcon="download">Export CSV</Button></div>
      </div>

      {view === "clause" ? (
        <div>
          {groupKeys.map((k) => <ClauseGroup key={k} ckey={k} rows={groups[k]} />)}
          {groupKeys.length === 0 && <Card padding={40} style={{ textAlign: "center", color: "var(--content-muted)" }}>No clauses match these filters.</Card>}
        </div>
      ) : (
        <Card style={{ overflow: "hidden" }}>
          <table style={{ width: "100%", borderCollapse: "collapse", fontSize: 13.5 }}>
            <thead>
              <tr style={{ background: "var(--bg-sunken)" }}>
                {["Clause", "Std #", "Provider", "Rd", "Risk", "Provider ask", "Our position / outcome", "State"].map((h) => (
                  <th key={h} style={{ textAlign: "left", padding: "10px 14px", fontSize: 11, fontWeight: 600, letterSpacing: "0.04em", textTransform: "uppercase", color: "var(--content-muted)", borderBottom: "1px solid var(--border-base)", whiteSpace: "nowrap" }}>{h}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {rows.map((r) => (
                <tr key={r.id} style={{ verticalAlign: "top" }} onMouseEnter={(e) => (e.currentTarget.style.background = "var(--bg-sunken)")} onMouseLeave={(e) => (e.currentTarget.style.background = "transparent")}>
                  <td style={{ padding: "12px 14px", borderBottom: "1px solid var(--border-subtle)", fontWeight: 500, color: "var(--content-strong)" }}>{r.clause}</td>
                  <td style={{ padding: "12px 14px", borderBottom: "1px solid var(--border-subtle)", fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--content-muted)" }}>{STD_CLAUSE[r.clauseKey]}</td>
                  <td style={{ padding: "12px 14px", borderBottom: "1px solid var(--border-subtle)", color: "var(--content-base)", whiteSpace: "nowrap" }}>{r.provider}</td>
                  <td style={{ padding: "12px 14px", borderBottom: "1px solid var(--border-subtle)", fontFamily: "var(--font-mono)", color: "var(--content-muted)" }}>R{r.round}</td>
                  <td style={{ padding: "12px 14px", borderBottom: "1px solid var(--border-subtle)" }}><RiskBadge risk={r.clauseRisk} style={ctx.riskStyle} size="sm" /></td>
                  <td style={{ padding: "12px 14px", borderBottom: "1px solid var(--border-subtle)", color: "var(--content-muted)", maxWidth: 200 }}>{r.providerAsk}</td>
                  <td style={{ padding: "12px 14px", borderBottom: "1px solid var(--border-subtle)", color: "var(--content-base)", maxWidth: 200 }}>{r.final || r.ourCounter}</td>
                  <td style={{ padding: "12px 14px", borderBottom: "1px solid var(--border-subtle)" }}><StatusBadge tone={STATE_MAP[r.state].tone}>{STATE_MAP[r.state].label}</StatusBadge></td>
                </tr>
              ))}
            </tbody>
          </table>
        </Card>
      )}
    </div>
  );
}

/* ── Audit trail ─────────────────────────────────────────────────────────*/
const ACTION_MAP = {
  upload:      { label: "Upload",        icon: "upload",        tone: "var(--status-info)" },
  classify:    { label: "Classify",      icon: "sparkles",      tone: "var(--green-700)" },
  omission:    { label: "Omission scan", icon: "file-x",        tone: "var(--status-warning)" },
  auto_accept: { label: "Auto-accept",   icon: "zap",           tone: "var(--content-muted)" },
  route:       { label: "Route",         icon: "route",         tone: "var(--green-700)" },
  decision:    { label: "Decision",      icon: "gavel",         tone: "var(--ec-primary)" },
  login:       { label: "Login",         icon: "log-in",        tone: "var(--content-muted)" },
  output:      { label: "Output sent",   icon: "send",          tone: "var(--status-success)" },
};

function AuditTrail({ log, search }) {
  const rows = (log || AUDIT).filter((e) => {
    const q = (search || "").trim().toLowerCase();
    return !q || [e.actor, e.action, e.target, e.detail].join(" ").toLowerCase().includes(q);
  });
  return (
    <div style={{ padding: 24, maxWidth: 940, margin: "0 auto" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 11, marginBottom: 16, padding: "13px 16px", background: "var(--ec-status-neutral-bg)", borderRadius: "var(--radius-lg)" }}>
        <Icon name="shield-check" size={18} style={{ color: "var(--content-muted)" }} />
        <div style={{ flex: 1 }}><div style={{ fontSize: 14, fontWeight: 600, color: "var(--content-strong)" }}>Immutable, tamper-evident log</div>
          <div style={{ fontSize: 12.5, color: "var(--content-muted)" }}>Every login, upload, classification, routing, decision and output is recorded with an actor, timestamp and hash. Read-only.</div></div>
        <Button variant="secondary" size="sm" leadingIcon="download">Export</Button>
      </div>
      <Card padding={0} style={{ overflow: "hidden" }}>
        {rows.map((e, i) => {
          const a = ACTION_MAP[e.action] || ACTION_MAP.decision;
          return (
            <div key={e.id} style={{ display: "flex", gap: 13, padding: "14px 18px", borderTop: i ? "1px solid var(--border-subtle)" : "none" }}>
              <span style={{ flex: "none", width: 32, height: 32, borderRadius: "var(--radius-md)", background: "var(--bg-sunken)", color: a.tone, display: "flex", alignItems: "center", justifyContent: "center" }}><Icon name={a.icon} size={16} /></span>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 2 }}>
                  <span style={{ fontSize: 13.5, fontWeight: 600, color: "var(--content-strong)" }}>{a.label}</span>
                  {e.target !== "—" && <span style={{ fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--content-muted)" }}>{e.target}</span>}
                  <span style={{ flex: 1 }} />
                  <span style={{ fontSize: 12.5, color: "var(--content-muted)" }}>{e.role}</span>
                </div>
                <div style={{ fontSize: 13, color: "var(--content-base)", lineHeight: 1.5 }}>{e.detail}</div>
                <div style={{ display: "flex", alignItems: "center", gap: 12, marginTop: 5 }}>
                  <span style={{ fontSize: 12, color: "var(--content-muted)" }}>{e.actor}</span>
                  <span style={{ fontSize: 12, color: "var(--content-faint)" }}>{timeAgo(Date.now() - e.mins * 60000)}</span>
                  <span style={{ fontFamily: "var(--font-mono)", fontSize: 11.5, color: "var(--content-faint)", display: "inline-flex", alignItems: "center", gap: 4 }}><Icon name="hash" size={11} />{e.hash}</span>
                </div>
              </div>
            </div>
          );
        })}
      </Card>
    </div>
  );
}

Object.assign(window, { Tracker, AuditTrail });
