// ---------- 9. Departments (站点部门 ⇄ OA 本地部门 绑定对账) ----------
// Primary task: reconcile site_department.local_dept_id bindings, NOT target
// operations. Grouped by site; each dept row is expandable to inspect the
// entry URLs (crawl_targets) attached to it.
const DEPT_STATE = { site: "", binding: "", q: "", expanded: new Set(), health: {} };
let DEPT_EDITOR = null;
let DEPT_LOCAL_OPTIONS = [];
let DEPT_SITE_OPTIONS = [];

function _bindingPill(b) {
  const m = { mapped: "green", pending: "amber", city_level: "blue", cross_dept: "slate", external_ref: "slate" };
  return pill(b, m[b] || "slate");
}
function _healthPill(row) {
  if (!row.enabled) return pill("停用", "slate");
  if (row.stale) return pill("stale", "red");
  return pill("正常", "green");
}

PAGES.departments = async () => {
  const ws = document.getElementById("workspace");
  ws.innerHTML = `<div class="text-slate-400 text-sm">加载中…</div>`;
  try {
    const [{ sites }, { items: localDepts }] = await Promise.all([
      api("/api/sites"),
      api("/api/local-departments?limit=500"),
    ]);
    DEPT_SITE_OPTIONS = sites;
    DEPT_LOCAL_OPTIONS = localDepts;

    const siteOpts = `<option value="">所有站点</option>` +
      sites.map(s => `<option value="${esc(s.site_code)}">${esc(s.site_code)} · ${esc(s.site_name || "")}</option>`).join("");

    ws.innerHTML = `
      ${pageBanner({
        title: "部门绑定对账",
        subtitle: "台账视图：站点部门路径 ⇄ OA 本地部门 的绑定状态（部门由爬虫自动发现，此处只做对账）",
      })}
      ${card({
        body: `
          <div class="filter-bar">
            <input id="d-q" class="filter-grow" placeholder="搜索 dept_path / 显示名…" value="${esc(DEPT_STATE.q)}" />
            <select id="d-site-f" style="width:240px">${siteOpts}</select>
            <select id="d-binding-f" style="width:150px">
              <option value="">绑定：全部</option>
              <option value="pending">pending 待绑</option>
              <option value="mapped">mapped 已绑</option>
              <option value="city_level">city_level</option>
              <option value="cross_dept">cross_dept</option>
              <option value="external_ref">external_ref</option>
            </select>
            <button class="btn-outline" onclick="resetDeptFilters()">重置</button>
          </div>
          <div id="d-groups"></div>`
      })}`;

    document.getElementById("d-site-f").value = DEPT_STATE.site;
    document.getElementById("d-binding-f").value = DEPT_STATE.binding;

    const rerender = () => loadDepartments();
    document.getElementById("d-q").oninput = (e) => { DEPT_STATE.q = e.target.value; rerender(); };
    document.getElementById("d-site-f").onchange = (e) => { DEPT_STATE.site = e.target.value; rerender(); };
    document.getElementById("d-binding-f").onchange = (e) => { DEPT_STATE.binding = e.target.value; rerender(); };

    loadDepartments();
  } catch (e) {
    ws.innerHTML = `<div class="card p-6 text-sm text-red-600">加载失败：${esc(e.message)}</div>`;
  }
};

function resetDeptFilters() {
  DEPT_STATE.q = ""; DEPT_STATE.site = ""; DEPT_STATE.binding = "";
  PAGES.departments();
}

async function loadDepartments() {
  const qs = new URLSearchParams({ limit: "5000" });
  if (DEPT_STATE.site) qs.set("site", DEPT_STATE.site);
  if (DEPT_STATE.binding) qs.set("binding", DEPT_STATE.binding);
  if (DEPT_STATE.q.trim()) qs.set("q", DEPT_STATE.q.trim());

  const box = document.getElementById("d-groups");
  box.innerHTML = `<div class="p-6 text-slate-400 text-sm">加载中…</div>`;
  try {
    const { count, items } = await api("/api/departments?" + qs);
    window.__deptRows = items;

    // Group by site_code
    const bySite = new Map();
    for (const d of items) {
      if (!bySite.has(d.site_code)) bySite.set(d.site_code, { site_code: d.site_code, site_name: "", rows: [] });
      bySite.get(d.site_code).rows.push(d);
      if (!bySite.get(d.site_code).site_name) {
        const s = DEPT_SITE_OPTIONS.find(s => s.site_code === d.site_code);
        if (s) bySite.get(d.site_code).site_name = s.site_name || "";
      }
    }

    if (!bySite.size) {
      box.innerHTML = `<div class="p-10 text-center text-slate-400 text-sm">无匹配的部门记录</div>`;
      return;
    }

    box.innerHTML = `
      <div class="px-5 py-2 border-b border-[#E5EBF1] text-xs text-slate-500">
        共 ${count} 个站点部门 · 涉及 ${bySite.size} 个站点 · pending ${items.filter(i => i.dept_binding === "pending").length} 条待绑
      </div>
      ${Array.from(bySite.values()).map(renderSiteGroup).join("")}`;
  } catch (e) {
    box.innerHTML = `<div class="card p-6 text-sm text-red-600">加载失败：${esc(e.message)}</div>`;
  }
}

function renderSiteGroup(group) {
  const depts = group.rows;
  const targetTotal = depts.reduce((a, d) => a + (d.target_count || 0), 0);
  const mapped = depts.filter(d => d.dept_binding === "mapped").length;
  return `
    <div class="border-b border-[#E5EBF1] last:border-b-0">
      <div class="px-5 py-3 bg-[#F8FAFC] flex items-center gap-3 text-sm">
        <span class="lu text-slate-500" style="font-size:14px">&#xe0eb;</span>
        <span class="font-semibold text-slate-900">${esc(group.site_code)}</span>
        <span class="text-slate-500 text-xs">${esc(group.site_name || "")}</span>
        <span class="ml-auto text-xs text-slate-500">${depts.length} 个部门 · ${targetTotal} 个入口 URL · 已绑 ${mapped}/${depts.length}</span>
      </div>
      <table class="w-full text-sm">
        <thead class="bg-white text-slate-500 text-xs border-b border-[#EEF2F7]">
          <tr>
            <th class="text-left pl-10 pr-4 py-2" style="width:28%">部门路径 / 显示名</th>
            <th class="text-left px-4 py-2" style="width:18%">绑定状态</th>
            <th class="text-left px-4 py-2">OA 本地部门</th>
            <th class="text-left px-4 py-2" style="width:120px">入口 URL 数</th>
            <th class="text-right px-4 py-2" style="width:200px">操作</th>
          </tr>
        </thead>
        <tbody>
          ${depts.map(d => renderDeptRow(d)).join("")}
        </tbody>
      </table>
    </div>`;
}

function renderDeptRow(d) {
  const isOpen = DEPT_STATE.expanded.has(d.id);
  const chev = isOpen ? "▾" : "▸";
  const detail = isOpen ? renderDeptTargetsRow(d) : "";
  return `
    <tr class="border-t border-slate-100 hover:bg-slate-50/50">
      <td class="pl-10 pr-4 py-2.5">
        <button onclick="toggleDeptExpand(${d.id})" class="flex items-center gap-2 text-left">
          <span class="text-slate-400 w-3">${chev}</span>
          <span>
            <span class="font-medium text-slate-800">${esc(d.dept_display_name || d.dept_path)}</span>
            <span class="block text-[11px] text-slate-400 mono">${esc(d.dept_path)}</span>
          </span>
        </button>
      </td>
      <td class="px-4 py-2.5">${_bindingPill(d.dept_binding)}${!d.enabled ? ` ${pill("停用","slate")}` : ""}</td>
      <td class="px-4 py-2.5 text-xs text-slate-600">
        ${d.local_dept_id
          ? `<span class="mono text-slate-700">${d.local_dept_id}</span><span class="text-slate-500"> · ${esc(d.local_dept_full_name || d.local_dept_name || "")}</span>`
          : `<span class="text-amber-600">未绑定</span>`}
      </td>
      <td class="px-4 py-2.5 text-xs">
        <button onclick="toggleDeptExpand(${d.id})" class="text-[#1D4ED8] hover:underline">${d.target_count || 0} 个入口</button>
      </td>
      <td class="px-4 py-2.5 text-right whitespace-nowrap">
        <button onclick="openDeptModal(${d.id})" class="text-xs px-2 py-1 rounded border border-slate-200 text-slate-700 hover:bg-slate-50">改绑</button>
        <button onclick="deleteDept(${d.id}, '${esc(d.dept_path)}', ${d.target_count})" class="text-xs px-2 py-1 rounded border border-red-200 text-red-600 hover:bg-red-50">删除</button>
      </td>
    </tr>
    ${detail}`;
}

function renderDeptTargetsRow(d) {
  const health = DEPT_STATE.health[d.id];
  const body = !health ? `<div class="p-4 text-xs text-slate-400">加载入口列表中…</div>`
    : !health.items.length ? `<div class="p-4 text-xs text-slate-400">该部门下暂无入口 URL</div>`
    : `<table class="w-full text-xs">
        <thead class="text-slate-500">
          <tr>
            <th class="text-left pl-12 pr-4 py-2">target_code / 名称</th>
            <th class="text-left px-4 py-2">栏目路径</th>
            <th class="text-left px-4 py-2">入口 URL</th>
            <th class="px-4 py-2" style="width:100px">节奏</th>
            <th class="px-4 py-2" style="width:100px">健康度</th>
            <th class="text-right pr-10 py-2" style="width:100px">操作</th>
          </tr>
        </thead>
        <tbody>
          ${health.items.map(t => `
            <tr class="border-t border-[#EEF2F7]">
              <td class="pl-12 pr-4 py-2">
                <div class="mono text-slate-700">${esc(t.target_code)}</div>
                <div class="text-slate-500">${esc(t.target_name || "—")}</div>
              </td>
              <td class="px-4 py-2 text-slate-600 max-w-[220px] truncate" title="${esc(t.channel_path || "")}">${esc(t.channel_path || t.channel_name || "—")}</td>
              <td class="px-4 py-2 text-slate-500 mono max-w-[260px] truncate" title="${esc(t.entry_url || "")}">${esc(t.entry_url || "—")}</td>
              <td class="px-4 py-2 text-center">每 ${esc(t.expected_cadence_days || "—")} 天</td>
              <td class="px-4 py-2 text-center">${_healthPill(t)}</td>
              <td class="pr-10 py-2 text-right">
                <button onclick="go('targets')" class="text-[#1D4ED8] hover:underline">去目标页</button>
              </td>
            </tr>`).join("")}
        </tbody>
      </table>`;
  return `<tr class="bg-[#F8FAFC]"><td colspan="5" class="p-0 border-t border-[#E5EBF1]">${body}</td></tr>`;
}

async function toggleDeptExpand(id) {
  if (DEPT_STATE.expanded.has(id)) {
    DEPT_STATE.expanded.delete(id);
    loadDepartments();
    return;
  }
  DEPT_STATE.expanded.add(id);
  loadDepartments();
  if (!DEPT_STATE.health[id]) {
    try {
      DEPT_STATE.health[id] = await api(`/api/departments/${id}/health`);
    } catch (e) {
      DEPT_STATE.health[id] = { items: [] };
    }
    loadDepartments();
  }
}

// ---------- Dept binding modal ----------
function _deptModalBody() {
  const current = DEPT_EDITOR || { dept_binding: "pending", enabled: true };
  const sites = DEPT_SITE_OPTIONS || [];
  const siteOpts = sites.map(s => `<option value="${esc(s.site_code)}" ${current.site_code === s.site_code ? "selected" : ""}>${esc(s.site_code)} · ${esc(s.site_name || "")}</option>`).join("");
  const bindings = ["pending","mapped","city_level","cross_dept","external_ref"];
  return `
    <div class="grid grid-cols-2 gap-4">
      <div><div class="field-label">所属站点</div><select id="d-edit-site" class="field-input" ${current.id ? "disabled" : ""}>${siteOpts}</select></div>
      <div><div class="field-label">dept_path</div><input id="d-edit-path" value="${esc(current.dept_path || "")}" class="field-input mono" placeholder="如: /edu/ 或 edu" ${current.id ? "disabled" : ""}/></div>
      <div><div class="field-label">显示名</div><input id="d-edit-name" value="${esc(current.dept_display_name || "")}" class="field-input" placeholder="如: 清远市教育局"/></div>
      <div><div class="field-label">绑定方式</div><select id="d-edit-binding" class="field-input">
        ${bindings.map(v => `<option value="${v}" ${current.dept_binding === v ? "selected" : ""}>${v}</option>`).join("")}
      </select></div>
      <div class="col-span-2"><div class="field-label">OA 本地部门（local_department）</div>${renderDeptSelect({ selectId: "d-edit-local", placeholder: "— 不绑定本地部门 —" })}
        <div class="field-hint">binding 为 mapped 时必须绑定；city_level / cross_dept / external_ref 可不绑</div>
      </div>
      <div class="col-span-2"><label class="flex items-center gap-2 text-sm"><input id="d-edit-enabled" type="checkbox" ${current.enabled ? "checked" : ""} /> <span>启用该部门映射</span></label></div>
    </div>`;
}

function openDeptModal(id) {
  if (id != null) {
    const row = (window.__deptRows || []).find(d => d.id === id);
    DEPT_EDITOR = row ? { ...row } : null;
  } else {
    DEPT_EDITOR = null;
  }
  openModal({
    title: DEPT_EDITOR && DEPT_EDITOR.id ? `改绑 · ${DEPT_EDITOR.site_code} · ${DEPT_EDITOR.dept_path}` : "新增站点部门映射",
    subtitle: "把站点上发现的部门路径绑定到 OA 里的权威部门 dept_id",
    body: _deptModalBody(),
    footer: `
      <button onclick="closeModal()" class="btn-ghost">取消</button>
      <button onclick="saveDeptEditor()" class="btn-primary">保存映射</button>`,
    wide: true,
    onClose: () => { DEPT_EDITOR = null; },
  });
  populateDeptSelect("d-edit-local", DEPT_LOCAL_OPTIONS || [], (DEPT_EDITOR || {}).local_dept_id || "");
}

async function saveDeptEditor() {
  const payload = {
    site_code: document.getElementById("d-edit-site").value,
    dept_path: document.getElementById("d-edit-path").value.trim(),
    dept_display_name: document.getElementById("d-edit-name").value.trim() || null,
    dept_binding: document.getElementById("d-edit-binding").value,
    local_dept_id: document.getElementById("d-edit-local").value ? Number(document.getElementById("d-edit-local").value) : null,
    enabled: document.getElementById("d-edit-enabled").checked,
  };
  try {
    if (DEPT_EDITOR && DEPT_EDITOR.id) {
      await api(`/api/departments/${DEPT_EDITOR.id}`, {
        method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload),
      });
      toast(`已更新 ${payload.dept_path}`);
    } else {
      await api("/api/departments", {
        method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload),
      });
      toast(`已新增 ${payload.dept_path}`);
    }
    DEPT_EDITOR = null;
    closeModal();
    // Invalidate cached health for this row so the expand refreshes fresh data
    loadDepartments();
  } catch (e) { toast(e.message, "err"); }
}

async function deleteDept(id, path, targetCount) {
  if (targetCount > 0) {
    toast(`该部门下仍有 ${targetCount} 个入口 URL，请先改挂或删除`, "err");
    return;
  }
  if (!confirm(`确认永久删除部门映射 ${path}？`)) return;
  try {
    await api(`/api/departments/${id}`, { method: "DELETE" });
    toast(`已删除 ${path}`);
    delete DEPT_STATE.health[id];
    DEPT_STATE.expanded.delete(id);
    loadDepartments();
  } catch (e) { toast(e.message, "err"); }
}
