// ============ DOMAINS TAB (CIT-423) ============
// The domain "tag manager": create/rename/recolor/delete the domain taxonomy,
// and decide pending domain_assignment requests raised by employees who
// aren't Admin/Owner. Direct CRUD + assignment is gated server-side by
// CAPABILITIES.DOMAIN_MANAGE (Admin/Owner/MasterAdmin) — this UI only shows
// the relevant actions per role, the server is the real gate.
//
// Also exports window.DomainPicker, a small reusable multi-select checkbox
// popover used here and from team.jsx / knowledge.jsx to assign/request
// domains against an employee or a knowledge doc.

const DOM_PALETTE = ["#E85D1A", "#3B7CFF", "#2DAF6B", "#B4488C", "#7A5BCF", "#D17C2A", "#3DA28A", "#C04545"];
const DOM_SERVER = () =>
  (typeof window !== "undefined" && window.CITRUS_CONFIG && window.CITRUS_CONFIG.SERVER_URL) ||
  "http://localhost:3001";

function domHeaders(extra = {}) {
  const hdrs = { "content-type": "application/json", ...extra };
  try {
    if (window.__citrusTenantSlug) hdrs["X-Tenant-Slug"] = window.__citrusTenantSlug;
    const token = localStorage.getItem("citrus_auth_token") || "";
    if (token) hdrs.Authorization = `Bearer ${token}`;
  } catch {}
  return hdrs;
}

function domFetch(path, options = {}) {
  const merged = { ...options };
  merged.headers = domHeaders(merged.headers || {});
  if (!Object.prototype.hasOwnProperty.call(merged, "credentials")) merged.credentials = "include";
  return fetch(`${DOM_SERVER()}${path}`, merged);
}

// Shared hook: loads the domain taxonomy + employee<->domain links once and
// exposes a reload() so callers can refresh after an assign/request.
function useDomainsList() {
  const [domains, setDomains] = useState([]);
  const [assignments, setAssignments] = useState([]);
  const [loading, setLoading] = useState(true);

  const reload = () => {
    setLoading(true);
    Promise.all([
      domFetch("/domains").then((r) => (r.ok ? r.json() : [])),
      domFetch("/domains/assignments").then((r) => (r.ok ? r.json() : [])),
    ])
      .then(([d, a]) => { setDomains(Array.isArray(d) ? d : []); setAssignments(Array.isArray(a) ? a : []); })
      .catch(() => {})
      .finally(() => setLoading(false));
  };

  useEffect(() => { reload(); }, []);

  return { domains, assignments, loading, reload };
}
window.useDomainsList = useDomainsList;

function DomainChip({ domain, onRemove }) {
  if (!domain) return null;
  return (
    <span className="dom-chip" style={{ background: `${domain.color}22`, color: domain.color, border: `1px solid ${domain.color}55` }}>
      {domain.name}
      {onRemove ? <button type="button" className="dom-chip-x" onClick={onRemove} aria-label={`Remove ${domain.name}`}>×</button> : null}
    </span>
  );
}
window.DomainChip = DomainChip;

// Reusable checkbox popover for picking a set of domain ids. `canApply`
// controls the button label/behavior: true → "Assign domains" applies
// immediately on save; false → "Request domains" (the caller decides what
// save() actually does — this component just collects the selection).
function DomainPicker({ domains, selectedIds, onSave, onClose, canApply, saving }) {
  const [picked, setPicked] = useState(new Set(selectedIds || []));
  const toggle = (id) => setPicked((prev) => {
    const next = new Set(prev);
    next.has(id) ? next.delete(id) : next.add(id);
    return next;
  });
  return (
    <div className="dom-picker" onMouseLeave={onClose}>
      {domains.length === 0 ? (
        <div className="dom-picker-empty">No domains yet — an Admin or Owner can create some in Settings → Domains.</div>
      ) : (
        <div className="dom-picker-list">
          {domains.map((d) => (
            <label key={d.id} className="dom-picker-item">
              <input type="checkbox" checked={picked.has(d.id)} onChange={() => toggle(d.id)} />
              <span className="dom-swatch" style={{ background: d.color }} />
              {d.name}
            </label>
          ))}
        </div>
      )}
      <div className="dom-picker-actions">
        <button className="btn btn-primary btn-sm" disabled={!!saving} onClick={() => onSave([...picked])}>
          {saving ? "Saving…" : canApply ? "Assign domains" : "Request domains"}
        </button>
        <button className="btn btn-ghost btn-sm" onClick={onClose}>Cancel</button>
      </div>
    </div>
  );
}
window.DomainPicker = DomainPicker;

function DomainsTab({ userRole } = {}) {
  const normalizedRole = String(userRole || "").trim().toLowerCase();
  const canManage = normalizedRole === "owner" || normalizedRole === "admin" || normalizedRole === "masteradmin";

  const { domains, reload: reloadDomains } = useDomainsList();
  const [requests, setRequests] = useState(null); // null = loading
  const [showAdd, setShowAdd] = useState(false);
  const [draftName, setDraftName] = useState("");
  const [draftColor, setDraftColor] = useState(DOM_PALETTE[0]);
  const [editingId, setEditingId] = useState(null);
  const [editName, setEditName] = useState("");
  const [busy, setBusy] = useState(null);

  const loadRequests = () => {
    if (!canManage) { setRequests([]); return; }
    domFetch("/approvals?status=pending")
      .then((r) => (r.ok ? r.json() : []))
      .then((rows) => setRequests((Array.isArray(rows) ? rows : []).filter((a) => a.kind === "domain_assignment")))
      .catch(() => setRequests([]));
  };
  useEffect(() => { loadRequests(); }, [canManage]);

  const createDomain = () => {
    const name = draftName.trim();
    if (!name) { window.toast && window.toast("Name a domain first", "warn"); return; }
    setBusy("create");
    domFetch("/domains", { method: "POST", body: JSON.stringify({ name, color: draftColor }) })
      .then((r) => (r.ok ? r.json() : r.json().then((j) => Promise.reject(j))))
      .then(() => { setDraftName(""); setShowAdd(false); reloadDomains(); window.toast && window.toast("Domain created", "good"); })
      .catch((j) => window.toast && window.toast(j?.error || "Couldn't create domain", "warn"))
      .finally(() => setBusy(null));
  };

  const saveRename = (domain) => {
    const name = editName.trim();
    if (!name) return;
    setBusy(domain.id);
    domFetch(`/domains/${domain.id}`, { method: "PATCH", body: JSON.stringify({ name }) })
      .then((r) => (r.ok ? r.json() : r.json().then((j) => Promise.reject(j))))
      .then(() => { setEditingId(null); reloadDomains(); window.toast && window.toast("Domain renamed", "good"); })
      .catch((j) => window.toast && window.toast(j?.error || "Couldn't rename domain", "warn"))
      .finally(() => setBusy(null));
  };

  const recolor = (domain, color) => {
    domFetch(`/domains/${domain.id}`, { method: "PATCH", body: JSON.stringify({ color }) })
      .then((r) => (r.ok ? r.json() : Promise.reject()))
      .then(() => reloadDomains())
      .catch(() => window.toast && window.toast("Couldn't recolor domain", "warn"));
  };

  const deleteDomain = (domain) => {
    if (!window.confirm(`Delete "${domain.name}"? Employees and docs tagged with it will lose the tag.`)) return;
    setBusy(domain.id);
    domFetch(`/domains/${domain.id}`, { method: "DELETE" })
      .then((r) => (r.ok ? r.json() : Promise.reject()))
      .then(() => { reloadDomains(); loadRequests(); window.toast && window.toast(`${domain.name} deleted`, "warn"); })
      .catch(() => window.toast && window.toast("Couldn't delete domain", "warn"))
      .finally(() => setBusy(null));
  };

  const decide = (approval, action) => {
    setBusy(approval.id);
    domFetch(`/approvals/${approval.id}/${action}`, { method: "POST", body: JSON.stringify({}) })
      .then((r) => (r.ok ? r.json() : r.json().then((j) => Promise.reject(j))))
      .then(() => {
        setRequests((xs) => xs.filter((a) => a.id !== approval.id));
        reloadDomains();
        window.toast && window.toast(action === "approve" ? "Request approved" : "Request declined", action === "approve" ? "good" : "warn");
      })
      .catch((j) => window.toast && window.toast(j?.error || "Couldn't decide request", "warn"))
      .finally(() => setBusy(null));
  };

  return (
    <div className="tm-page">
      <div className="tm-head">
        <div>
          <h2 className="tm-h">Domains.</h2>
          <p className="tm-s">Tag employees and knowledge docs by domain so agents route leads and pull in the right knowledge automatically.</p>
        </div>
        {canManage ? <button className="btn btn-primary btn-sm" onClick={() => setShowAdd(true)}>+ Add domain</button> : null}
      </div>

      {!canManage ? (
        <div className="tm-card" style={{ padding: "0.85rem 1rem", border: "1px solid var(--border)", borderRadius: 8, color: "var(--ink-2)", fontSize: "0.85rem" }}>
          Only Owners and Admins can create, rename, or delete domains. Ask one of them, or request domains for yourself from your row in Team & permissions.
        </div>
      ) : null}

      <div className="tm-list">
        {domains.length === 0 ? (
          <div className="tm-row" style={{ color: "var(--ink-soft)", fontSize: "0.85rem" }}>No domains yet.</div>
        ) : domains.map((d) => (
          <div key={d.id} className="tm-row" style={{ gridTemplateColumns: "auto 1fr auto" }}>
            <input
              type="color"
              value={d.color}
              disabled={!canManage}
              onChange={(e) => recolor(d, e.target.value)}
              title="Domain color"
              style={{ width: 28, height: 28, padding: 0, border: "none", background: "none", cursor: canManage ? "pointer" : "default" }}
            />
            <div className="tm-body">
              {editingId === d.id ? (
                <input
                  className="tm-add-i"
                  value={editName}
                  autoFocus
                  onChange={(e) => setEditName(e.target.value)}
                  onKeyDown={(e) => { if (e.key === "Enter") saveRename(d); if (e.key === "Escape") setEditingId(null); }}
                />
              ) : (
                <div className="tm-n">{d.name}</div>
              )}
            </div>
            {canManage ? (
              editingId === d.id ? (
                <div style={{ display: "flex", gap: 6 }}>
                  <button className="btn btn-primary btn-sm" disabled={busy === d.id} onClick={() => saveRename(d)}>Save</button>
                  <button className="btn btn-ghost btn-sm" onClick={() => setEditingId(null)}>Cancel</button>
                </div>
              ) : (
                <div style={{ display: "flex", gap: 6 }}>
                  <button className="btn btn-ghost btn-sm" onClick={() => { setEditingId(d.id); setEditName(d.name); }}>Rename</button>
                  <button className="btn btn-ghost btn-sm" style={{ color: "#B0234A" }} disabled={busy === d.id} onClick={() => deleteDomain(d)}>Delete</button>
                </div>
              )
            ) : null}
          </div>
        ))}
        {canManage && showAdd ? (
          <div className="tm-add">
            <input
              className="tm-add-i"
              placeholder="Domain name (e.g. HVAC, Plumbing)"
              value={draftName}
              onChange={(e) => setDraftName(e.target.value)}
              onKeyDown={(e) => { if (e.key === "Enter") createDomain(); if (e.key === "Escape") setShowAdd(false); }}
              autoFocus
            />
            <input type="color" value={draftColor} onChange={(e) => setDraftColor(e.target.value)} style={{ width: 36, height: 36, padding: 0, border: "1px solid var(--border)", borderRadius: 10 }} />
            <button className="btn btn-primary btn-sm" disabled={busy === "create"} onClick={createDomain}>Save</button>
            <button className="btn btn-ghost btn-sm" onClick={() => { setShowAdd(false); setDraftName(""); }}>Cancel</button>
          </div>
        ) : null}
      </div>

      {canManage ? (
        <div className="tm-audit">
          <div className="tm-audit-head">
            <h3 className="tm-audit-h">Pending domain requests</h3>
            <span className="tm-audit-s">Employees who requested domains for themselves</span>
          </div>
          {requests === null ? (
            <div className="tm-s" style={{ padding: "0.5rem 0" }}>Loading…</div>
          ) : requests.length === 0 ? (
            <div className="tm-s" style={{ padding: "0.5rem 0" }}>Nothing pending.</div>
          ) : (
            <div className="tm-list" style={{ marginTop: 8 }}>
              {requests.map((a) => (
                <div key={a.id} className="tm-row" style={{ gridTemplateColumns: "1fr auto auto" }}>
                  <div className="tm-body">
                    <div className="tm-n">{a.title}</div>
                    <div className="tm-e">{a.targetType === "knowledge" ? "Knowledge doc" : "Employee"} · requested {a.createdAt ? new Date(a.createdAt).toLocaleDateString(undefined, { month: "short", day: "numeric" }) : "recently"}</div>
                  </div>
                  <button className="btn btn-ghost btn-sm" style={{ color: "#B0234A" }} disabled={busy === a.id} onClick={() => decide(a, "reject")}>Decline</button>
                  <button className="btn btn-primary btn-sm" disabled={busy === a.id} onClick={() => decide(a, "approve")}>Approve</button>
                </div>
              ))}
            </div>
          )}
        </div>
      ) : null}
    </div>
  );
}
window.DomainsTab = DomainsTab;
