/* =========================================================
   Action Routing — configuration surface (the place where the
   tenant tells the agent WHO to email and WHO to copy, per
   department and per issue type, when a call produces an action).
   =========================================================
   Three sections:
     1. Departments — the teams. Each has a "Notify (To)" list, an
        "Always CC" list, an SLA target, an escalation contact and a
        digest cadence.
     2. Routing rules — "when <issue type> happens, route to <department>",
        with optional To/CC overrides, urgency override, and a
        human-review vs auto-send mode (auto needs a 2nd approver).
     3. Guardrails — the internal-domain allowlist (every recipient must
        sit inside it; anti-leak), a tenant-wide always-CC, and a pause.
   Endpoints: /action-routing/{departments,rules,settings}
   (CRUD + /rules/{id}/approve). All tenant-scoped.
   ========================================================= */

const RC_ISSUE_TYPES = [
  { v: "default", label: "Everything else (catch-all)" },
  { v: "fraud_dispute", label: "Fraud / dispute — regulated" },
  { v: "complaint", label: "Complaint — regulated" },
  { v: "card_swallowed", label: "Card swallowed / retained" },
  { v: "failed_transaction", label: "Failed transaction / no cash" },
  { v: "account_access", label: "Account access / PIN / OTP" },
  { v: "loan_inquiry", label: "Loan / sales inquiry" },
  { v: "branch_info", label: "Branch info / opening hours" },
  { v: "general", label: "General inquiry" },
];
const RC_MODES = [
  { v: "auto", label: "Auto-send (needs a 2nd approver)" },
  { v: "human_review", label: "Human review — never auto-sent" },
  { v: "needs_approval", label: "Needs approval each time" },
  { v: "template_auto", label: "Template auto-send" },
];
const RC_URGENCY = ["", "critical", "high", "normal", "low"];
const RC_CADENCE = ["immediate", "hourly", "end_of_shift", "daily"];
const RC_REGULATED = new Set(["fraud_dispute", "complaint"]);

const rcDedupe = (xs) => {
  const seen = new Set(), out = [];
  (xs || []).forEach((x) => { const v = String(x || "").trim(); if (v && !seen.has(v)) { seen.add(v); out.push(v); } });
  return out;
};
const rcMatchLabel = (m) => {
  if (!m || m.default) return "Everything else (catch-all)";
  const it = (RC_ISSUE_TYPES.find((x) => x.v === m.issue_type) || {}).label;
  return it || m.issue_type || "—";
};

/* ---- a small email/domain list editor (chips + add field) ---- */
const RcChips = ({ value, onChange, placeholder, normalize }) => {
  const [draft, setDraft] = React.useState("");
  const list = Array.isArray(value) ? value : [];
  const commit = () => {
    const parts = draft.split(/[,\s]+/).map((s) => s.trim()).filter(Boolean).map((s) => (normalize ? normalize(s) : s));
    if (parts.length) onChange(rcDedupe([...list, ...parts]));
    setDraft("");
  };
  return (
    <div>
      {list.length > 0 && (
        <div style={{ display: "flex", flexWrap: "wrap", gap: 6, marginBottom: 6 }}>
          {list.map((e, i) => (
            <span key={i} style={{ display: "inline-flex", alignItems: "center", gap: 6, fontSize: 12.5, background: "var(--surface-2, rgba(0,0,0,.05))", border: "1px solid var(--border, rgba(0,0,0,.1))", borderRadius: 999, padding: "3px 8px" }}>
              {e}
              <button type="button" onClick={() => onChange(list.filter((x) => x !== e))} style={{ border: "none", background: "none", cursor: "pointer", color: "var(--fg-muted)", fontSize: 14, lineHeight: 1, padding: 0 }}>×</button>
            </span>
          ))}
        </div>
      )}
      <input
        className="input"
        value={draft}
        placeholder={placeholder || "type, then Enter or comma"}
        onChange={(e) => setDraft(e.target.value)}
        onKeyDown={(e) => { if (e.key === "Enter" || e.key === ",") { e.preventDefault(); commit(); } }}
        onBlur={commit}
      />
    </div>
  );
};

const RcField = ({ label, hint, children }) => (
  <div className="field" style={{ marginBottom: 12 }}>
    <label>{label}</label>
    {children}
    {hint && <div style={{ fontSize: 11.5, color: "var(--fg-muted)", marginTop: 4 }}>{hint}</div>}
  </div>
);

/* ============================ departments ============================ */
const RcDepartmentForm = ({ initial, onSave, onCancel, busy }) => {
  const [d, setD] = React.useState(() => ({
    name: "", default_emails: [], cc: [], sla_hours: 24, digest_cadence: "end_of_shift",
    escalate_to: {}, business_tz: "Africa/Nairobi", enabled: true, ...(initial || {}),
  }));
  const set = (k, v) => setD((p) => ({ ...p, [k]: v }));
  const escEmail = (d.escalate_to && d.escalate_to.email) || "";
  return (
    <div className="card card-pad" style={{ borderLeft: "3px solid var(--mk-accent, var(--fg))" }}>
      <RcField label="Department name"><input className="input" value={d.name} onChange={(e) => set("name", e.target.value)} placeholder="e.g. Fraud & disputes" /></RcField>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
        <RcField label="Notify — To" hint="The team that owns this department's actions."><RcChips value={d.default_emails} onChange={(v) => set("default_emails", v)} placeholder="fraud-ops@bank.co.ke" /></RcField>
        <RcField label="Always CC" hint="Standing watchers copied on every action for this department."><RcChips value={d.cc} onChange={(v) => set("cc", v)} placeholder="compliance@bank.co.ke" /></RcField>
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 14 }}>
        <RcField label="SLA target (hours)"><input className="input" type="number" min="1" value={d.sla_hours ?? ""} onChange={(e) => set("sla_hours", e.target.value === "" ? null : parseInt(e.target.value, 10))} /></RcField>
        <RcField label="Digest cadence" hint="Normal/low items batch into one email per window.">
          <select className="input" value={d.digest_cadence} onChange={(e) => set("digest_cadence", e.target.value)}>{RC_CADENCE.map((c) => <option key={c} value={c}>{c}</option>)}</select>
        </RcField>
        <RcField label="Escalation contact" hint="Notified if the SLA is breached."><input className="input" value={escEmail} onChange={(e) => set("escalate_to", e.target.value ? { email: e.target.value } : {})} placeholder="head-of-dept@bank.co.ke" /></RcField>
      </div>
      <label style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 13, marginBottom: 12 }}>
        <input type="checkbox" checked={!!d.enabled} onChange={(e) => set("enabled", e.target.checked)} /> Enabled
      </label>
      <div className="row" style={{ gap: 8 }}>
        <button className="btn btn-accent btn-sm" disabled={busy || !d.name.trim()} onClick={() => onSave(d)}>{busy ? "Saving…" : "Save department"}</button>
        <button className="btn btn-ghost btn-sm" disabled={busy} onClick={onCancel}>Cancel</button>
      </div>
    </div>
  );
};

/* ============================ rules ============================ */
const RcRuleForm = ({ initial, departments, onSave, onCancel, busy }) => {
  const initMatch = (initial && initial.match) || {};
  const [r, setR] = React.useState(() => ({
    department_id: (departments[0] || {}).id || null,
    destination_emails: [], cc: [], urgency_override: "", mode: "auto",
    sla_hours: null, regulated: false, enabled: true, ...(initial || {}),
    issue_key: initMatch.default ? "default" : (initMatch.issue_type || (initial && initial.issue_key) || "default"),
  }));
  const set = (k, v) => setR((p) => ({ ...p, [k]: v }));
  const isReg = RC_REGULATED.has(r.issue_key);
  return (
    <div className="card card-pad" style={{ borderLeft: "3px solid var(--mk-accent, var(--fg))" }}>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
        <RcField label="When the call is about…">
          <select className="input" value={r.issue_key} onChange={(e) => set("issue_key", e.target.value)}>{RC_ISSUE_TYPES.map((t) => <option key={t.v} value={t.v}>{t.label}</option>)}</select>
        </RcField>
        <RcField label="Route to department">
          <select className="input" value={r.department_id || ""} onChange={(e) => set("department_id", e.target.value || null)}>
            <option value="">— pick a department —</option>
            {departments.map((d) => <option key={d.id} value={d.id}>{d.name}</option>)}
          </select>
        </RcField>
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
        <RcField label="To override" hint="Optional — leave empty to use the department's To list."><RcChips value={r.destination_emails} onChange={(v) => set("destination_emails", v)} placeholder="(uses department default)" /></RcField>
        <RcField label="Extra CC for this issue" hint="Added on top of the department + tenant CC."><RcChips value={r.cc} onChange={(v) => set("cc", v)} placeholder="e.g. branch-manager@bank.co.ke" /></RcField>
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 14 }}>
        <RcField label="Urgency override"><select className="input" value={r.urgency_override || ""} onChange={(e) => set("urgency_override", e.target.value)}>{RC_URGENCY.map((u) => <option key={u} value={u}>{u || "(auto from issue)"}</option>)}</select></RcField>
        <RcField label="Handling" hint={isReg ? "Regulated issues are always forced to human review." : undefined}>
          <select className="input" value={isReg ? "human_review" : r.mode} disabled={isReg} onChange={(e) => set("mode", e.target.value)}>{RC_MODES.map((m) => <option key={m.v} value={m.v}>{m.label}</option>)}</select>
        </RcField>
        <RcField label="SLA override (hours)"><input className="input" type="number" min="1" value={r.sla_hours ?? ""} onChange={(e) => set("sla_hours", e.target.value === "" ? null : parseInt(e.target.value, 10))} placeholder="(department / tier)" /></RcField>
      </div>
      <label style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 13, marginBottom: 12 }}>
        <input type="checkbox" checked={!!r.enabled} onChange={(e) => set("enabled", e.target.checked)} /> Enabled
      </label>
      <div className="row" style={{ gap: 8 }}>
        <button className="btn btn-accent btn-sm" disabled={busy || !r.department_id} onClick={() => onSave(r)}>{busy ? "Saving…" : "Save rule"}</button>
        <button className="btn btn-ghost btn-sm" disabled={busy} onClick={onCancel}>Cancel</button>
      </div>
    </div>
  );
};

/* ============================ main ============================ */
const RoutingConfig = ({ onGo }) => {
  const toast = useToast();
  const [tab, setTab] = React.useState("departments");
  const [depts, setDepts] = React.useState([]);
  const [rules, setRules] = React.useState([]);
  const [settings, setSettings] = React.useState({ internal_email_domains: [], default_cc: [], paused: false });
  const [loading, setLoading] = React.useState(true);
  const [err, setErr] = React.useState(null);
  const [busy, setBusy] = React.useState(false);
  const [editDept, setEditDept] = React.useState(null); // {} for new, row for edit, null hidden
  const [editRule, setEditRule] = React.useState(null);

  const reload = React.useCallback(async () => {
    const [d, r, s] = await Promise.all([
      apiRequest("/action-routing/departments"),
      apiRequest("/action-routing/rules"),
      apiRequest("/action-routing/settings").catch(() => ({ internal_email_domains: [], default_cc: [], paused: false })),
    ]);
    setDepts(Array.isArray(d) ? d : []);
    setRules(Array.isArray(r) ? r : []);
    setSettings(s || { internal_email_domains: [], default_cc: [], paused: false });
  }, []);

  React.useEffect(() => {
    let live = true;
    (async () => { try { await reload(); } catch (e) { if (live) setErr(String((e && e.message) || e)); } finally { if (live) setLoading(false); } })();
    return () => { live = false; };
  }, [reload]);

  const fail = (e, title) => toast({ title: title || "Couldn’t save", body: String((e && e.message) || e), kind: "danger" });
  const deptName = (id) => (depts.find((x) => x.id === id) || {}).name || "—";
  const noAllowlist = !((settings.internal_email_domains || []).length);

  // ---- department actions ----
  const saveDept = async (d) => {
    setBusy(true);
    try {
      const payload = { name: d.name, default_emails: d.default_emails || [], cc: d.cc || [], sla_hours: d.sla_hours, escalate_to: d.escalate_to || {}, business_tz: d.business_tz || "Africa/Nairobi", digest_cadence: d.digest_cadence || "end_of_shift", enabled: !!d.enabled };
      if (d.id) await apiRequest(`/action-routing/departments/${d.id}`, { method: "PATCH", body: JSON.stringify(payload) });
      else await apiRequest("/action-routing/departments", { method: "POST", body: JSON.stringify(payload) });
      toast({ title: d.id ? "Department updated" : "Department added" });
      setEditDept(null); await reload();
    } catch (e) { fail(e); } finally { setBusy(false); }
  };
  const delDept = async (id) => {
    if (typeof window !== "undefined" && !window.confirm("Delete this department? Rules pointing at it will stop routing.")) return;
    setBusy(true);
    try { await apiRequest(`/action-routing/departments/${id}`, { method: "DELETE" }); toast({ title: "Department deleted" }); await reload(); }
    catch (e) { fail(e, "Couldn’t delete"); } finally { setBusy(false); }
  };

  // ---- rule actions ----
  const saveRule = async (r) => {
    setBusy(true);
    try {
      const match = r.issue_key === "default" ? { default: true } : { issue_type: r.issue_key };
      const payload = { department_id: r.department_id, match, channel: "email", destination_emails: r.destination_emails || [], cc: r.cc || [], urgency_override: r.urgency_override || null, mode: RC_REGULATED.has(r.issue_key) ? "human_review" : r.mode, sla_hours: r.sla_hours, regulated: RC_REGULATED.has(r.issue_key) || !!r.regulated, enabled: !!r.enabled };
      if (r.id) await apiRequest(`/action-routing/rules/${r.id}`, { method: "PATCH", body: JSON.stringify(payload) });
      else await apiRequest("/action-routing/rules", { method: "POST", body: JSON.stringify(payload) });
      toast({ title: r.id ? "Rule updated — re-approval needed" : "Rule added — awaiting a 2nd approver" });
      setEditRule(null); await reload();
    } catch (e) { fail(e); } finally { setBusy(false); }
  };
  const approveRule = async (id) => {
    setBusy(true);
    try { await apiRequest(`/action-routing/rules/${id}/approve`, { method: "POST", body: JSON.stringify({}) }); toast({ title: "Rule approved" }); await reload(); }
    catch (e) { fail(e, "Couldn’t approve"); } finally { setBusy(false); }
  };
  const delRule = async (id) => {
    if (typeof window !== "undefined" && !window.confirm("Delete this routing rule?")) return;
    setBusy(true);
    try { await apiRequest(`/action-routing/rules/${id}`, { method: "DELETE" }); toast({ title: "Rule deleted" }); await reload(); }
    catch (e) { fail(e, "Couldn’t delete"); } finally { setBusy(false); }
  };

  // ---- settings ----
  const saveSettings = async (patch) => {
    setBusy(true);
    try { const s = await apiRequest("/action-routing/settings", { method: "PUT", body: JSON.stringify(patch) }); setSettings(s); toast({ title: "Guardrails saved" }); }
    catch (e) { fail(e, "Couldn’t save guardrails"); } finally { setBusy(false); }
  };

  if (loading) return <div className="card card-pad">Loading configuration…</div>;
  if (err) return <div className="card card-pad" style={{ color: "var(--mk-danger)" }}>Couldn’t load: {err}</div>;

  const ruleActive = (r) => !!r.enabled && (r.mode !== "auto" || (r.approved_by && r.approved_by !== r.created_by));

  return (
    <div className="stack" style={{ gap: 18 }}>
      <div className="row between">
        <h2 style={{ margin: 0 }}>Action routing</h2>
        <div style={{ fontSize: 13, color: "var(--fg-muted)" }}>Tell the agent who to email — and who to copy — for each kind of call</div>
      </div>

      {noAllowlist && (
        <div className="card card-pad" style={{ borderLeft: "3px solid var(--mk-warning)" }}>
          <div style={{ fontWeight: 600, color: "var(--mk-warning)" }}>Set your internal email domains first</div>
          <div style={{ fontSize: 12.5, color: "var(--fg-muted)", marginTop: 2 }}>Until then, email destinations can’t be saved — it’s the guardrail that stops customer data leaving your organisation. Open the <button className="btn btn-ghost btn-sm" onClick={() => setTab("guardrails")} style={{ padding: "0 4px" }}>Guardrails</button> tab.</div>
        </div>
      )}

      <div className="row" style={{ gap: 6, flexWrap: "wrap" }}>
        {[["departments", "Departments"], ["rules", "Routing rules"], ["guardrails", "Guardrails"], ["policy", "Policy compiler"]].map(([k, label]) => (
          <button key={k} className={tab === k ? "btn btn-accent btn-sm" : "btn btn-outline btn-sm"} onClick={() => setTab(k)}>{label}</button>
        ))}
      </div>

      {/* ---------------- departments ---------------- */}
      {tab === "departments" && (
        <div className="stack" style={{ gap: 12 }}>
          {depts.length === 0 && !editDept && <div className="card card-pad" style={{ fontSize: 13, color: "var(--fg-muted)" }}>No departments yet. Add the teams that should receive call actions.</div>}
          {depts.map((d) => (
            <div key={d.id} className="card card-pad">
              <div className="row between" style={{ alignItems: "flex-start" }}>
                <div>
                  <div style={{ fontWeight: 600 }}>{d.name} {!d.enabled && <span style={{ fontSize: 11.5, color: "var(--fg-muted)" }}>(disabled)</span>}</div>
                  <div style={{ fontSize: 12.5, color: "var(--fg-muted)", marginTop: 4 }}>
                    <strong>To:</strong> {(d.default_emails || []).join(", ") || "—"}　·　<strong>CC:</strong> {(d.cc || []).join(", ") || "—"}
                  </div>
                  <div style={{ fontSize: 12, color: "var(--fg-muted)", marginTop: 2 }}>SLA {d.sla_hours ?? "—"}h · {d.digest_cadence} digest{d.escalate_to && d.escalate_to.email ? ` · escalates to ${d.escalate_to.email}` : ""}</div>
                </div>
                <div className="row" style={{ gap: 6 }}>
                  <button className="btn btn-outline btn-sm" onClick={() => setEditDept(d)}>Edit</button>
                  <button className="btn btn-ghost btn-sm" onClick={() => delDept(d.id)}>Delete</button>
                </div>
              </div>
              {editDept && editDept.id === d.id && <div style={{ marginTop: 12 }}><RcDepartmentForm initial={editDept} onSave={saveDept} onCancel={() => setEditDept(null)} busy={busy} /></div>}
            </div>
          ))}
          {editDept && !editDept.id && <RcDepartmentForm initial={editDept} onSave={saveDept} onCancel={() => setEditDept(null)} busy={busy} />}
          {!editDept && <div><button className="btn btn-accent btn-sm" onClick={() => setEditDept({})}>+ Add department</button></div>}
        </div>
      )}

      {/* ---------------- rules ---------------- */}
      {tab === "rules" && (
        <div className="stack" style={{ gap: 12 }}>
          {depts.length === 0 && <div className="card card-pad" style={{ fontSize: 13, color: "var(--fg-muted)" }}>Add at least one department before creating rules.</div>}
          {rules.map((r) => (
            <div key={r.id} className="card card-pad">
              <div className="row between" style={{ alignItems: "flex-start" }}>
                <div>
                  <div style={{ fontWeight: 600 }}>{rcMatchLabel(r.match)} → {deptName(r.department_id)}</div>
                  <div style={{ fontSize: 12.5, color: "var(--fg-muted)", marginTop: 4 }}>
                    {r.mode === "human_review" ? "Human review" : r.mode}{r.urgency_override ? ` · ${r.urgency_override}` : ""}{(r.destination_emails || []).length ? ` · To: ${r.destination_emails.join(", ")}` : ""}{(r.cc || []).length ? ` · +CC: ${r.cc.join(", ")}` : ""}
                  </div>
                  <div style={{ fontSize: 12, marginTop: 3, color: ruleActive(r) ? "var(--mk-success)" : "var(--mk-warning)" }}>
                    {ruleActive(r) ? "● Active" : (r.mode === "auto" ? "● Awaiting a 2nd approver" : "● Disabled")}{r.regulated ? " · regulated" : ""}
                  </div>
                </div>
                <div className="row" style={{ gap: 6 }}>
                  {r.mode === "auto" && !ruleActive(r) && <button className="btn btn-accent btn-sm" onClick={() => approveRule(r.id)}>Approve</button>}
                  <button className="btn btn-outline btn-sm" onClick={() => setEditRule({ ...r, issue_key: r.match && r.match.default ? "default" : (r.match || {}).issue_type })}>Edit</button>
                  <button className="btn btn-ghost btn-sm" onClick={() => delRule(r.id)}>Delete</button>
                </div>
              </div>
              {editRule && editRule.id === r.id && <div style={{ marginTop: 12 }}><RcRuleForm initial={editRule} departments={depts} onSave={saveRule} onCancel={() => setEditRule(null)} busy={busy} /></div>}
            </div>
          ))}
          {editRule && !editRule.id && <RcRuleForm initial={editRule} departments={depts} onSave={saveRule} onCancel={() => setEditRule(null)} busy={busy} />}
          {!editRule && depts.length > 0 && <div><button className="btn btn-accent btn-sm" onClick={() => setEditRule({})}>+ Add rule</button></div>}
        </div>
      )}

      {/* ---------------- guardrails ---------------- */}
      {tab === "guardrails" && (
        <RcGuardrails settings={settings} onSave={saveSettings} busy={busy} />
      )}

      {/* ---------------- policy compiler ---------------- */}
      {tab === "policy" && (
        <RcPolicy onApplied={() => { reload(); setTab("departments"); }} />
      )}
    </div>
  );
};

const RcGuardrails = ({ settings, onSave, busy }) => {
  const [domains, setDomains] = React.useState(settings.internal_email_domains || []);
  const [cc, setCc] = React.useState(settings.default_cc || []);
  const [paused, setPaused] = React.useState(!!settings.paused);
  return (
    <div className="stack" style={{ gap: 12 }}>
      <div className="card card-pad">
        <div style={{ fontWeight: 600, marginBottom: 4 }}>Internal email domains (allowlist)</div>
        <div style={{ fontSize: 12.5, color: "var(--fg-muted)", marginBottom: 10 }}>Every To/CC address must sit inside one of these domains — at save time and again at send time. This is the hard guardrail that stops customer information being emailed outside your organisation.</div>
        <RcChips value={domains} onChange={setDomains} placeholder="bank.co.ke" normalize={(s) => s.toLowerCase().replace(/^@/, "").trim()} />
      </div>
      <div className="card card-pad">
        <div style={{ fontWeight: 600, marginBottom: 4 }}>Always CC (tenant-wide)</div>
        <div style={{ fontSize: 12.5, color: "var(--fg-muted)", marginBottom: 10 }}>Copied on every routed action, on top of each department’s and rule’s CC. Useful for a shared compliance or audit mailbox. Must be inside the allowlist above.</div>
        <RcChips value={cc} onChange={setCc} placeholder="audit@bank.co.ke" />
      </div>
      <div className="card card-pad">
        <label style={{ display: "flex", alignItems: "center", gap: 10, fontSize: 13.5 }}>
          <input type="checkbox" checked={paused} onChange={(e) => setPaused(e.target.checked)} />
          <span><strong>Pause all routing</strong> — kill switch. The agent keeps classifying, but no actions dispatch.</span>
        </label>
      </div>
      <div><button className="btn btn-accent btn-sm" disabled={busy} onClick={() => onSave({ internal_email_domains: domains, default_cc: cc, paused })}>{busy ? "Saving…" : "Save guardrails"}</button></div>
    </div>
  );
};

/* ============================ policy compiler ============================ */
const RcProposalView = ({ proposal, onApply, onReject, busy }) => {
  const p = (proposal && proposal.proposed) || {};
  const depts = p.departments || [];
  const rules = p.rules || [];
  const guard = p.guardrails || {};
  const assumptions = p.assumptions || [];
  const applied = proposal.status === "applied";
  return (
    <div className="card card-pad" style={{ borderLeft: "3px solid var(--mk-accent, var(--fg))" }}>
      <div className="row between">
        <div style={{ fontWeight: 600 }}>Proposed from “{proposal.source_title}”</div>
        <span style={{ fontSize: 12, textTransform: "capitalize", color: applied ? "var(--mk-success)" : "var(--fg-muted)" }}>{proposal.status}</span>
      </div>
      {p.summary && <div style={{ fontSize: 13, marginTop: 6 }}>{p.summary}</div>}

      <div style={{ marginTop: 12, fontWeight: 600, fontSize: 13 }}>Departments ({depts.length})</div>
      {depts.map((d, i) => (
        <div key={i} style={{ fontSize: 12.5, color: "var(--fg-muted)", marginTop: 4 }}>
          <strong style={{ color: "var(--fg)" }}>{d.name}</strong> — To: {(d.default_emails || []).join(", ") || "—"} · CC: {(d.cc || []).join(", ") || "—"} · SLA {d.sla_hours ?? "—"}h{d.escalation_email ? ` · escalates ${d.escalation_email}` : ""}
        </div>
      ))}

      <div style={{ marginTop: 12, fontWeight: 600, fontSize: 13 }}>Rules ({rules.length})</div>
      {rules.map((r, i) => (
        <div key={i} style={{ fontSize: 12.5, color: "var(--fg-muted)", marginTop: 4 }}>
          {r.issue_type} → <strong style={{ color: "var(--fg)" }}>{r.department_name || "—"}</strong> · {r.regulated ? "human review (regulated)" : (r.mode || "auto")}{r.urgency_override ? ` · ${r.urgency_override}` : ""}{(r.destination_emails || []).length ? ` · To: ${r.destination_emails.join(", ")}` : ""}
        </div>
      ))}

      <div style={{ marginTop: 12, fontWeight: 600, fontSize: 13 }}>Guardrails</div>
      <div style={{ fontSize: 12.5, color: "var(--fg-muted)", marginTop: 4 }}>
        Internal domains: {(guard.internal_email_domains || []).join(", ") || "—"} · Always-CC: {(guard.default_cc || []).join(", ") || "—"}
      </div>

      {assumptions.length > 0 && (
        <div className="card card-pad" style={{ marginTop: 12, borderLeft: "3px solid var(--mk-warning)" }}>
          <div style={{ fontWeight: 600, color: "var(--mk-warning)", fontSize: 12.5 }}>Review these — inferred or missing from the document:</div>
          <ul style={{ margin: "4px 0 0 16px", fontSize: 12.5, color: "var(--fg-muted)" }}>{assumptions.map((a, i) => <li key={i}>{a}</li>)}</ul>
        </div>
      )}

      <div style={{ fontSize: 11.5, color: "var(--fg-muted)", marginTop: 12 }}>Applying creates/updates departments and creates rules <strong>unapproved</strong> — each auto-send rule still needs a second approver before it routes. Recipients outside your internal domains are dropped.</div>
      {proposal.status === "draft" && (
        <div className="row" style={{ gap: 8, marginTop: 10 }}>
          <button className="btn btn-accent btn-sm" disabled={busy} onClick={() => onApply(proposal.id)}>{busy ? "Applying…" : "Apply to config"}</button>
          <button className="btn btn-ghost btn-sm" disabled={busy} onClick={() => onReject(proposal.id)}>Reject</button>
        </div>
      )}
    </div>
  );
};

const RcPolicy = ({ onApplied }) => {
  const toast = useToast();
  const [sources, setSources] = React.useState([]);
  const [proposals, setProposals] = React.useState([]);
  const [pick, setPick] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const [loading, setLoading] = React.useState(true);

  const load = async () => {
    const [docsRes, props] = await Promise.all([
      apiRequest("/onboarding/documents").catch(() => ({ documents: [] })),
      apiRequest("/action-routing/policy/proposals").catch(() => []),
    ]);
    const docs = (((docsRes && docsRes.documents) || [])).filter((d) => d.visibility === "internal_only");
    setSources(docs);
    setProposals(Array.isArray(props) ? props : []);
  };
  React.useEffect(() => { let live = true; (async () => { try { await load(); } finally { if (live) setLoading(false); } })(); return () => { live = false; }; }, []);

  const fail = (e, t) => toast({ title: t || "Failed", body: String((e && e.message) || e), kind: "danger" });
  const compile = async () => {
    if (!pick) return;
    setBusy(true);
    try {
      await apiRequest("/action-routing/policy/compile", { method: "POST", body: JSON.stringify({ document_id: pick }) });
      toast({ title: "Policy compiled", body: "Review the proposal below, then apply." });
      setPick(""); await load();
    } catch (e) { fail(e, "Compile failed"); } finally { setBusy(false); }
  };
  const apply = async (id) => {
    setBusy(true);
    try {
      const res = await apiRequest(`/action-routing/policy/proposals/${id}/apply`, { method: "POST", body: JSON.stringify({}) });
      toast({ title: "Applied to config", body: `${res.departments_created || 0} new departments · ${res.rules_created || 0} rules (awaiting approval).` });
      await load(); if (onApplied) onApplied();
    } catch (e) { fail(e, "Apply failed"); } finally { setBusy(false); }
  };
  const reject = async (id) => {
    setBusy(true);
    try { await apiRequest(`/action-routing/policy/proposals/${id}/reject`, { method: "POST", body: JSON.stringify({}) }); await load(); }
    catch (e) { fail(e, "Reject failed"); } finally { setBusy(false); }
  };

  if (loading) return <div className="card card-pad">Loading…</div>;
  const drafts = proposals.filter((p) => p.status === "draft");
  const past = proposals.filter((p) => p.status !== "draft");

  return (
    <div className="stack" style={{ gap: 12 }}>
      <div className="card card-pad">
        <div style={{ fontWeight: 600, marginBottom: 4 }}>Compile policy from a document</div>
        <div style={{ fontSize: 12.5, color: "var(--fg-muted)", marginBottom: 10 }}>
          Keep your routing / SLA / escalation policy as a document, marked <strong>Internal-only</strong> in the Knowledge Base. Mikaka reads it and proposes the structured departments, rules and guardrails below — you review and apply. Nothing routes until you apply <em>and</em> approve each rule.
        </div>
        {sources.length === 0 ? (
          <div style={{ fontSize: 12.5, color: "var(--fg-muted)" }}>No internal-only sources yet. In <strong>AI receptionist → Knowledge Base</strong>, upload your policy document and set its visibility to “Internal-only”.</div>
        ) : (
          <div className="row" style={{ gap: 8, flexWrap: "wrap" }}>
            <select className="input" value={pick} onChange={(e) => setPick(e.target.value)} style={{ maxWidth: 360 }}>
              <option value="">— pick an internal-only document —</option>
              {sources.map((d) => <option key={d.id} value={d.id}>{d.file_name || d.title || d.id}</option>)}
            </select>
            <button className="btn btn-accent btn-sm" disabled={busy || !pick} onClick={compile}>{busy ? "Compiling…" : "Compile policy"}</button>
          </div>
        )}
      </div>

      {drafts.map((p) => <RcProposalView key={p.id} proposal={p} onApply={apply} onReject={reject} busy={busy} />)}

      {past.length > 0 && (
        <div className="card card-pad">
          <div style={{ fontWeight: 600, marginBottom: 8 }}>History</div>
          {past.map((p) => (
            <div key={p.id} style={{ fontSize: 12.5, color: "var(--fg-muted)", marginTop: 4 }}>
              {p.source_title} — <span style={{ textTransform: "capitalize", color: p.status === "applied" ? "var(--mk-success)" : "var(--fg-muted)" }}>{p.status}</span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
};
