/* approval-docs.jsx — panel trong Documents: XEM trạng thái phê duyệt tài liệu (read-only),
   + nút "Gửi duyệt" cho editor/admin. window.ApprovalDocs. */
(function () {
  const { useState, useEffect } = React;
  const Icon = window.Icon;

  function ApprovalDocs() {
    const auth = (typeof useAuthCtx === "function") ? useAuthCtx() : null;
    const role = (auth && auth.profile && auth.profile.role) || (auth && auth.user ? "viewer" : "admin");
    const canManage = role === "editor" || role === "admin";
    const [insts, setInsts] = useState([]);
    const [active, setActive] = useState(null);
    const [docs, setDocs] = useState([]);
    const [open, setOpen] = useState(false);
    const [pick, setPick] = useState("");
    const [busy, setBusy] = useState(false);
    const [myRoles, setMyRoles] = useState([]);

    const reload = () => {
      if (window.cdeApprovalRun) window.cdeApprovalRun.instances().then(setInsts).catch(() => {});
      if (window.cdeApproval) window.cdeApproval.list().then(l => setActive((l || []).find(w => w.active) || null)).catch(() => {});
      if (window.cdeData) window.cdeData.containers().then(setDocs).catch(() => {});
      if (window.cdeRoles) window.cdeRoles.myRoleIds().then(setMyRoles).catch(() => {});
    };
    useEffect(reload, []);
    useEffect(() => {
      const h = () => reload();
      window.addEventListener("cde-approval-changed", h);
      return () => window.removeEventListener("cde-approval-changed", h);
    }, []);
    const ping = () => { try { window.dispatchEvent(new Event("cde-approval-changed")); } catch (e) {} };

    const gateLabel = (inst) => {
      const cfg = inst.config || {}; const node = (cfg.nodes || []).find(n => n.key === inst.currentNode);
      if (!node) return inst.status === "approved" ? "Hoàn tất" : inst.status === "rejected" ? "Bị từ chối" : "—";
      const g = (cfg.gates || []).find(x => x.id === node.gateId); return g ? g.name : node.key;
    };
    const progress = (inst) => { const n = (inst.config && inst.config.nodes) || []; const i = n.findIndex(x => x.key === inst.currentNode); return n.length ? { i: (i < 0 ? n.length : i + 1), n: n.length } : null; };
    const outcomesOf = (inst) => { const cfg = inst.config || {}; const node = (cfg.nodes || []).find(n => n.key === inst.currentNode); if (!node) return []; const g = (cfg.gates || []).find(x => x.id === node.gateId); return g ? g.outcomes : []; };
    const gateOf = (inst) => { const cfg = inst.config || {}; const node = (cfg.nodes || []).find(n => n.key === inst.currentNode); return node && (cfg.gates || []).find(x => x.id === node.gateId); };
    // ai được duyệt cổng này: admin luôn được; editor được nếu cổng không gán vai trò, hoặc giữ một vai trò của cổng
    const canActOn = (inst) => {
      if (role === "admin") return true;
      if (role !== "editor") return false;
      const gr = (gateOf(inst) || {}).roles || [];
      if (!gr.length) return true;
      return gr.some(id => myRoles.includes(id));
    };

    const inApproval = new Set(insts.filter(i => i.status === "running").map(i => i.containerId));
    const submit = async () => {
      if (!pick || !active) return; setBusy(true);
      try { await window.cdeApprovalRun.submit(pick, active.id); setPick(""); setOpen(false); reload(); ping(); }
      catch (e) { alert("Gửi duyệt thất bại: " + e.message); } finally { setBusy(false); }
    };
    const advance = async (inst, ok) => { try { await window.cdeApprovalRun.advance(inst.id, ok, (auth && auth.profile && auth.profile.full_name) || "Tôi"); reload(); ping(); } catch (e) { alert(e.message); } };
    const cancel = async (inst) => { if (!window.confirm('Thu hồi "' + inst.docName + '" khỏi luồng phê duyệt?')) return; try { await window.cdeApprovalRun.cancel(inst.id, (auth && auth.profile && auth.profile.full_name) || "Tôi"); reload(); ping(); } catch (e) { alert(e.message); } };

    const stChip = (s) => s === "approved" ? ["ok", "Đã duyệt"] : s === "rejected" ? ["danger", "Từ chối"] : s === "cancelled" ? ["idle", "Đã huỷ"] : ["warn", "Đang duyệt"];

    return (
      <div className="apd">
        <div className="apd-head">
          <div className="apd-title"><Icon.checkCircle size={16} /> Phê duyệt tài liệu</div>
          {active ? <span className="apd-active">Luồng: <b>{active.name}</b></span> : <span className="apd-noactive">Chưa có luồng kích hoạt</span>}
          {canManage && active && <button className="btn sm primary apd-send" onClick={() => setOpen(o => !o)}><Icon.send size={13} /> Gửi duyệt</button>}
        </div>

        {open && canManage && (
          <div className="apd-submit">
            <select className="ae2-sel" value={pick} onChange={(e) => setPick(e.target.value)}>
              <option value="">— Chọn tài liệu —</option>
              {docs.filter(d => !inApproval.has(d.id)).map(d => <option key={d.id} value={d.id}>{d.name}</option>)}
            </select>
            <span className="apd-arrow">→ {active.name}</span>
            <button className="btn sm primary" disabled={!pick || busy} onClick={submit}>{busy ? "…" : "Gửi"}</button>
          </div>
        )}

        {!insts.length && <div className="apd-empty">Chưa có tài liệu nào trong luồng phê duyệt.</div>}
        {insts.map(inst => {
          const [cls, lbl] = stChip(inst.status); const pg = progress(inst);
          return (
            <div className="apd-row" key={inst.id}>
              <span className="apd-doc"><Icon.doc size={14} /> {inst.docName}</span>
              <span className="apd-wf">{inst.wfName}</span>
              <span className="apd-step">{gateLabel(inst)}{pg && inst.status === "running" ? ` · bước ${pg.i}/${pg.n}` : ""}</span>
              <span className={"chip " + cls} style={{ height: 22 }}>{lbl}</span>
              {inst.status === "running" && (canActOn(inst) || canManage) && (
                <span className="apd-acts">
                  {canActOn(inst)
                    ? outcomesOf(inst).map(o => (
                        <button key={o.key} className="apd-out" style={{ borderColor: o.color, color: o.color }} onClick={() => advance(inst, o.key)}>{o.label}</button>
                      ))
                    : <span className="apd-norole" title="Bạn không có vai trò được duyệt cổng này">Chờ vai trò khác duyệt</span>}
                  {canManage && <button className="apd-out apd-cancel" title="Thu hồi khỏi luồng" onClick={() => cancel(inst)}>Huỷ</button>}
                </span>
              )}
            </div>
          );
        })}
      </div>
    );
  }

  window.ApprovalDocs = ApprovalDocs;
})();
