// ============================================================================
// IMS — Admin: Assignments Overview  (OS + CM variants)
// variant: "outreach" | "collab"
// List → drill-down detail per specialist/manager. No nested expand state.
// ============================================================================

const PERSON_PER_PAGE = 10;
const INF_PER_PAGE    = 10;

// ── Main list page ────────────────────────────────────────────────────────────

function AssignmentsPage({ variant }) {
  const { data, setPage } = useApp();
  const isOS = variant === "outreach";

  const [search, setSearch] = useState("");
  const [pg, setPg]         = useState(1);
  const [detail, setDetail] = useState(null); // person row or null

  const allRows = useMemo(() => {
    const people = isOS
      ? (data.outreachSpecialists || []).filter(s => !s.deletedAt)
      : (data.collabManagers     || []).filter(m => !m.deletedAt);

    return people.map(p => {
      const pendingBundles = isOS
        ? (data.osInbox || []).filter(b => b.specialistId === p.id && b.state === "pending")
        : (data.cmInbox || []).filter(b => b.cmId         === p.id && b.state === "pending");

      const pendingCount = pendingBundles.reduce((n, b) => n + (b.influencers?.length || 0), 0);

      const active = isOS
        ? (data.outreachInProgress || []).filter(r => r.specialistId === p.id && !r.deletedAt && r.status !== "Dropped")
        : (data.collabInProgress   || []).filter(r => r.cmId === p.id && !r.deletedAt && r.stageState !== "Complete" && r.stageState !== "Dropped");

      const completed = isOS
        ? 0
        : (data.collabInProgress || []).filter(r => r.cmId === p.id && !r.deletedAt && r.stageState === "Complete").length;

      // Pre-compute summary counts to avoid per-card filters in render
      let statusSummary = {}, stageSummary = {};
      if (isOS) {
        active.forEach(r => {
          if (r.status === "Contacted")  statusSummary.contacted  = (statusSummary.contacted  || 0) + 1;
          if (r.status === "Interested") statusSummary.interested = (statusSummary.interested || 0) + 1;
        });
      } else {
        active.forEach(r => { stageSummary[r.currentStage] = (stageSummary[r.currentStage] || 0) + 1; });
      }

      return { person: p, pendingBundles, pendingCount, active, completed, statusSummary, stageSummary };
    });
  }, [data, isOS]);

  const filtered = useMemo(() => {
    if (!search.trim()) return allRows;
    const q = search.toLowerCase();
    return allRows.filter(r =>
      r.person.name.toLowerCase().includes(q) ||
      r.person.id.toLowerCase().includes(q)
    );
  }, [allRows, search]);

  const handleSearch = (v) => { setSearch(v); setPg(1); };
  const totalPages = Math.max(1, Math.ceil(filtered.length / PERSON_PER_PAGE));
  const paged = filtered.slice((pg - 1) * PERSON_PER_PAGE, pg * PERSON_PER_PAGE);

  const title    = isOS ? "OS Assignments" : "CM Assignments";
  const subtitle = isOS
    ? "Per-specialist overview — click a row to see their bundles and active influencers."
    : "Per-manager overview — click a row to see their bundles and active influencers.";

  // Show detail drill-down
  if (detail) {
    return (
      <PersonDetailPage
        row={detail}
        variant={variant}
        onBack={() => setDetail(null)}
        onRow={inf => setPage({ key: "profile", influencer: inf, from: "assignments" })}
      />
    );
  }

  return (
    <div className="page">
      <div className="page-head">
        <div>
          <h1>{title}</h1>
          <div className="subtitle">{subtitle}</div>
        </div>
        <div className="meta">
          <span>{allRows.length} {isOS ? "specialists" : "managers"}</span>
        </div>
      </div>

      <div className="toolbar">
        <AssignKpiStrip rows={allRows} variant={variant} />
        <div className="spacer" />
        <div className="search">
          <Ic.search />
          <input
            placeholder={`Search ${isOS ? "specialist" : "manager"} name or ID…`}
            value={search}
            onChange={e => handleSearch(e.target.value)}
          />
          {search && <button className="search-clear" onClick={() => handleSearch("")}><Ic.x /></button>}
        </div>
      </div>

      {filtered.length === 0 && (
        <div style={{ textAlign: "center", padding: "64px 0", color: "var(--ink-3)", fontFamily: "var(--font-mono)", fontSize: 12, letterSpacing: "0.06em" }}>
          {search ? "NO RESULTS — try a different search" : `NO ${isOS ? "OUTREACH SPECIALISTS" : "COLLABORATION MANAGERS"} FOUND`}
        </div>
      )}

      {paged.length > 0 && (
        <div className="table-wrap">
          <table className="ims">
            <thead>
              <tr>
                <th>{isOS ? "Specialist" : "Manager"}</th>
                <th className="num">Pending</th>
                <th className="num">Active</th>
                {!isOS && <th className="num">Completed</th>}
                <th className="num">Total</th>
                <th>{isOS ? "Status" : "Stage spread"}</th>
              </tr>
            </thead>
            <tbody>
              {paged.map(row => {
                const { person, pendingCount, active, completed } = row;
                const initials = person.name.split(" ").map(w => w[0]).join("").slice(0, 2).toUpperCase();
                const total = pendingCount + active.length;
                const idle  = total === 0;

                // Summary counts pre-built in allRows useMemo via row.summary
                let summary;
                if (isOS) {
                  const { contacted = 0, interested = 0 } = row.statusSummary || {};
                  summary = idle ? <Chip tone="neutral" xs>Idle</Chip> : (
                    <span className="text-xs text-mute">
                      {contacted > 0 && `${contacted} contacted`}
                      {contacted > 0 && interested > 0 && " · "}
                      {interested > 0 && `${interested} interested`}
                    </span>
                  );
                } else {
                  const byStage = row.stageSummary || {};
                  summary = idle ? <Chip tone="neutral" xs>Idle</Chip> : (
                    <span className="text-xs text-mute">
                      {[1,2,3,4].filter(n => byStage[n]).map(n => `S${n}:${byStage[n]}`).join(" · ")}
                    </span>
                  );
                }

                return (
                  <tr key={person.id} className="clickable" onClick={() => setDetail(row)}>
                    <td>
                      <div className="inf-cell">
                        <div className="avatar">{initials}</div>
                        <div className="name-block">
                          <div className="name">{person.name}</div>
                          <div className="handle">{person.id}</div>
                        </div>
                      </div>
                    </td>
                    <td className="num">
                      {pendingCount > 0
                        ? <span style={{ color: "var(--alert-2)", fontWeight: 600 }}>{pendingCount}</span>
                        : <span className="text-mute">0</span>}
                    </td>
                    <td className="num">{active.length}</td>
                    {!isOS && <td className="num" style={{ color: completed > 0 ? "var(--ok)" : "var(--ink-4)" }}>{completed}</td>}
                    <td className="num">{total}</td>
                    <td>{summary}</td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      )}

      <TablePagination page={pg} totalPages={totalPages} onPage={setPg} total={filtered.length} perPage={PERSON_PER_PAGE} />
    </div>
  );
}

// ── Bundle card with per-bundle influencer pagination ─────────────────────────

const BUNDLE_INF_PER_PAGE = 8;

function BundleInfluencerCard({ bundle, searchQ, onDrop, cmLabel }) {
  const [pg, setPg] = useState(1);

  const allInfs = bundle.influencers || [];
  const filtered = searchQ.trim()
    ? allInfs.filter(inf =>
        inf.name.toLowerCase().includes(searchQ.toLowerCase()) ||
        inf.handle.toLowerCase().includes(searchQ.toLowerCase())
      )
    : allInfs;

  const totalPages = Math.max(1, Math.ceil(filtered.length / BUNDLE_INF_PER_PAGE));
  const paged = filtered.slice((pg - 1) * BUNDLE_INF_PER_PAGE, pg * BUNDLE_INF_PER_PAGE);

  // Reset page when search changes
  React.useEffect(() => { setPg(1); }, [searchQ]);

  const isLead = bundle.id.startsWith("LB");

  return (
    <div className="card" style={{ padding: 0, overflow: "hidden" }}>
      {/* Bundle header */}
      <div style={{ display: "flex", alignItems: "center", gap: 10, padding: "10px 14px", background: "var(--bg-2)", borderBottom: "1px solid var(--line)", flexWrap: "wrap" }}>
        <BundleIdChip id={bundle.id} />
        <Chip tone={isLead ? "accent" : "info"} xs>{isLead ? "Lead Bundle" : "Outreach Bundle"}</Chip>
        {bundle.campaignName && <Chip tone="info" xs>{bundle.campaignName}</Chip>}
        {cmLabel && <span className="text-mono text-xs text-mute">{cmLabel} ·</span>}
        <span className="text-mono text-xs text-mute">
          {allInfs.length} influencer{allInfs.length !== 1 ? "s" : ""} · Assigned {bundle.assignedAt || "—"}
        </span>
        <div style={{ marginLeft: "auto" }}>
          <button
            className="btn sm"
            style={{ background: "var(--alert)", color: "#fff", borderColor: "var(--alert)", fontSize: 11 }}
            onClick={() => onDrop(bundle)}
          >
            Drop Bundle
          </button>
        </div>
      </div>
      {/* Influencers table */}
      {filtered.length === 0 ? (
        <div style={{ padding: "16px 14px", color: "var(--ink-3)", fontFamily: "var(--font-mono)", fontSize: 12 }}>
          {searchQ ? "NO MATCHES IN THIS BUNDLE" : "NO INFLUENCERS"}
        </div>
      ) : (
        <>
          <table className="ims" style={{ margin: 0 }}>
            <thead>
              <tr>
                <th>Influencer</th>
                <th>Platform</th>
                <th>Followers</th>
                <th>Category</th>
              </tr>
            </thead>
            <tbody>
              {paged.map(inf => (
                <tr key={inf.id}>
                  <td><InfCell name={inf.name} handle={inf.handle} /></td>
                  <td className="text-small">{inf.platform}</td>
                  <td className="text-small">{inf.followers}</td>
                  <td className="text-small">{inf.category}</td>
                </tr>
              ))}
            </tbody>
          </table>
          {totalPages > 1 && (
            <div style={{ padding: "4px 8px", borderTop: "1px solid var(--line)" }}>
              <TablePagination page={pg} totalPages={totalPages} onPage={setPg} total={filtered.length} perPage={BUNDLE_INF_PER_PAGE} />
            </div>
          )}
        </>
      )}
    </div>
  );
}

// ── Drop Bundle confirmation modal ────────────────────────────────────────────

function DropBundleModal({ bundle, specialistName, isOS, onConfirm, onClose }) {
  const infCount = bundle.influencers?.length || 0;
  const [reason, setReason] = React.useState("");
  return (
    <Modal open onClose={onClose} title="Drop Bundle" size="sm">
      <div className="banner warn" style={{ marginBottom: 16 }}>
        <Ic.warn />
        <div>
          <strong>This action cannot be undone.</strong> The specialist will be notified and all influencers will return to the unassigned pool.
        </div>
      </div>
      <div style={{ display: "flex", flexDirection: "column", gap: 10, marginBottom: 20 }}>
        {[
          ["Bundle", bundle.id],
          ["Assigned to", specialistName],
          ["Influencers", `${infCount} will return to unassigned`],
          ...(bundle.campaignName ? [["Campaign", bundle.campaignName]] : []),
          ["Assigned", bundle.assignedAt || "—"],
        ].map(([l, v]) => (
          <div key={l} style={{ display: "flex", justifyContent: "space-between", alignItems: "center", borderBottom: "1px solid var(--line)", paddingBottom: 8 }}>
            <span className="text-mono text-xs text-mute" style={{ textTransform: "uppercase", letterSpacing: "0.08em" }}>{l}</span>
            <span style={{ fontSize: 13, fontWeight: 500 }}>{v}</span>
          </div>
        ))}
      </div>
      <div style={{ marginBottom: 20 }}>
        <label style={{ display: "block", fontSize: 11, fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.08em", color: "var(--ink-3)", marginBottom: 6 }}>
          Reason <span style={{ fontWeight: 400, textTransform: "none", letterSpacing: 0 }}>(optional)</span>
        </label>
        <textarea
          value={reason}
          onChange={e => setReason(e.target.value)}
          placeholder="e.g. OS unresponsive, bundle reassigned…"
          rows={3}
          style={{ width: "100%", resize: "vertical", fontSize: 13, padding: "8px 10px", borderRadius: 6, border: "1px solid var(--line-2)", background: "var(--surface)", color: "var(--ink)", boxSizing: "border-box" }}
        />
      </div>
      <div style={{ display: "flex", justifyContent: "flex-end", gap: 8 }}>
        <button className="btn ghost" onClick={onClose}>Cancel</button>
        <button className="btn" style={{ background: "var(--alert)", color: "#fff", borderColor: "var(--alert)" }} onClick={() => onConfirm(reason.trim())}>
          Drop Bundle
        </button>
      </div>
    </Modal>
  );
}

// ── Drill-down detail for one specialist/manager ──────────────────────────────

const BUNDLE_LIST_PER_PAGE = 5;

function PersonDetailPage({ row, variant, onBack, onRow }) {
  const { dropBundle, notify } = useApp();
  const { person, pendingBundles, active } = row;
  const isOS = variant === "outreach";

  const [tab, setTab]           = useState("active");
  const [activePg, setActivePg] = useState(1);
  const [bundleListPg, setBundleListPg] = useState(1);
  const [activeSearch, setActiveSearch] = useState("");
  const [bundleSearch, setBundleSearch] = useState("");
  const [dropTarget, setDropTarget] = useState(null);

  const totalPendingInf = pendingBundles.reduce((n, b) => n + (b.influencers?.length || 0), 0);

  const filteredActive = useMemo(() => {
    if (!activeSearch.trim()) return active;
    const q = activeSearch.toLowerCase();
    return active.filter(r => r.name.toLowerCase().includes(q) || r.handle.toLowerCase().includes(q));
  }, [active, activeSearch]);

  // Filter bundles by bundle ID, campaign name, or any influencer name/handle
  const filteredBundles = useMemo(() => {
    if (!bundleSearch.trim()) return pendingBundles;
    const q = bundleSearch.toLowerCase();
    return pendingBundles.filter(b =>
      b.id.toLowerCase().includes(q) ||
      (b.campaignName || "").toLowerCase().includes(q) ||
      (b.influencers || []).some(inf =>
        inf.name.toLowerCase().includes(q) || inf.handle.toLowerCase().includes(q)
      )
    );
  }, [pendingBundles, bundleSearch]);

  const bundleTotalPages = Math.max(1, Math.ceil(filteredBundles.length / BUNDLE_LIST_PER_PAGE));
  const pagedBundles = filteredBundles.slice((bundleListPg - 1) * BUNDLE_LIST_PER_PAGE, bundleListPg * BUNDLE_LIST_PER_PAGE);

  const handleActiveSearch = v => { setActiveSearch(v); setActivePg(1); };
  const handleBundleSearch = v => { setBundleSearch(v); setBundleListPg(1); };

  const aTotalPages = Math.max(1, Math.ceil(filteredActive.length / INF_PER_PAGE));
  const aPaged = filteredActive.slice((activePg - 1) * INF_PER_PAGE, activePg * INF_PER_PAGE);

  const initials = person.name.split(" ").map(w => w[0]).join("").slice(0, 2).toUpperCase();

  const handleDropConfirm = (reason) => {
    dropBundle(dropTarget.id, isOS ? "outreach" : "collab", reason);
    notify(`Bundle ${dropTarget.id} dropped — ${dropTarget.influencers?.length || 0} influencer(s) returned to unassigned pool.`);
    setDropTarget(null);
    setBundleListPg(1);
  };

  return (
    <div className="page">
      <button className="btn ghost sm" onClick={onBack} style={{ marginBottom: 16 }}>
        <Ic.arrowLeft /> {isOS ? "OS Assignments" : "CM Assignments"}
      </button>

      {/* Header */}
      <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 20 }}>
        <div style={{ width: 40, height: 40, borderRadius: "50%", background: "var(--accent-bg)", color: "var(--accent)", display: "flex", alignItems: "center", justifyContent: "center", fontFamily: "var(--font-mono)", fontSize: 14, fontWeight: 700, flexShrink: 0 }}>{initials}</div>
        <div>
          <h1 style={{ margin: 0 }}>{person.name}</h1>
          <div className="text-mono text-xs text-mute">{person.id} · {isOS ? "Outreach Specialist" : "Collaboration Manager"} · {person.country}</div>
        </div>
        <div style={{ marginLeft: "auto", display: "flex", gap: 0, border: "1px solid var(--line)", borderRadius: 2 }}>
          <AssignKpi label="Pending"  value={totalPendingInf} hot={totalPendingInf > 0} />
          <AssignKpi label="Active"   value={active.length} />
          <AssignKpi label="Total"    value={totalPendingInf + active.length} last />
        </div>
      </div>

      {/* Tabs + search */}
      <div className="toolbar" style={{ marginBottom: 12 }}>
        <div className="tabs" style={{ margin: 0 }}>
          <div className={`tab ${tab === "active" ? "active" : ""}`}
            onClick={() => { setTab("active"); setActivePg(1); setActiveSearch(""); }}>
            Active ({active.length})
          </div>
          <div className={`tab ${tab === "pending" ? "active" : ""}`}
            onClick={() => { setTab("pending"); setBundleListPg(1); setBundleSearch(""); }}>
            Pending Bundles ({pendingBundles.length})
          </div>
        </div>
        <div className="spacer" />
        {tab === "active" && (
          <div className="search">
            <Ic.search />
            <input placeholder="Search influencer…" value={activeSearch}
              onChange={e => handleActiveSearch(e.target.value)} />
            {activeSearch && <button className="search-clear" onClick={() => handleActiveSearch("")}><Ic.x /></button>}
          </div>
        )}
        {tab === "pending" && (
          <div className="search">
            <Ic.search />
            <input placeholder="Search bundle, campaign or influencer…" value={bundleSearch}
              onChange={e => handleBundleSearch(e.target.value)} />
            {bundleSearch && <button className="search-clear" onClick={() => handleBundleSearch("")}><Ic.x /></button>}
          </div>
        )}
      </div>

      {/* Active tab */}
      {tab === "active" && (
        <>
          {filteredActive.length === 0 ? (
            <div style={{ textAlign: "center", padding: "48px 0", color: "var(--ink-3)", fontFamily: "var(--font-mono)", fontSize: 12, letterSpacing: "0.06em" }}>
              {activeSearch ? "NO MATCHES" : "NO ACTIVE INFLUENCERS"}
            </div>
          ) : (
            <div className="table-wrap">
              <table className="ims">
                <thead>
                  <tr>
                    <th>Influencer</th>
                    <th>Platform</th>
                    <th>Followers</th>
                    <th>Category</th>
                    {isOS ? <th>Status</th> : <th>Stage</th>}
                    {isOS ? <th>Bundle</th> : <th>Campaign</th>}
                    {!isOS && <th>Bundle</th>}
                  </tr>
                </thead>
                <tbody>
                  {aPaged.map(r => (
                    <tr key={r.assignmentId || r.id} className="clickable" onClick={() => onRow(r)}>
                      <td><InfCell name={r.name} handle={r.handle} /></td>
                      <td className="text-small">{r.platform}</td>
                      <td className="text-small">{r.followers}</td>
                      <td className="text-small">{r.category}</td>
                      {isOS
                        ? <td>{r.status ? <StatusChip status={r.status} /> : <span className="text-mute">—</span>}</td>
                        : <td>{r.stages ? <StageBar stages={r.stages} currentStage={r.currentStage} stageState={r.stageState} /> : <span className="text-mute">—</span>}</td>}
                      {isOS
                        ? <td>{r.bundleId ? <BundleIdChip id={r.bundleId} /> : <span className="text-mute">—</span>}</td>
                        : <td>{r.campaignName ? <Chip tone="info" xs>{r.campaignName}</Chip> : <span className="text-mute">—</span>}</td>}
                      {!isOS && <td>{r.bundleId ? <BundleIdChip id={r.bundleId} /> : <span className="text-mute">—</span>}</td>}
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}
          <TablePagination page={activePg} totalPages={aTotalPages} onPage={setActivePg} total={filteredActive.length} perPage={INF_PER_PAGE} />
        </>
      )}

      {/* Pending bundles tab */}
      {tab === "pending" && (
        <>
          {filteredBundles.length === 0 ? (
            <div style={{ textAlign: "center", padding: "48px 0", color: "var(--ink-3)", fontFamily: "var(--font-mono)", fontSize: 12, letterSpacing: "0.06em" }}>
              {bundleSearch ? "NO BUNDLES MATCH YOUR SEARCH" : "NO PENDING BUNDLES"}
            </div>
          ) : (
            <>
              <div style={{ display: "flex", flexDirection: "column", gap: 12, marginBottom: 12 }}>
                {pagedBundles.map(b => (
                  <BundleInfluencerCard
                    key={b.id}
                    bundle={b}
                    searchQ={bundleSearch}
                    onDrop={setDropTarget}
                  />
                ))}
              </div>
              <TablePagination
                page={bundleListPg}
                totalPages={bundleTotalPages}
                onPage={setBundleListPg}
                total={filteredBundles.length}
                perPage={BUNDLE_LIST_PER_PAGE}
              />
            </>
          )}
        </>
      )}

      {dropTarget && (
        <DropBundleModal
          bundle={dropTarget}
          specialistName={person.name}
          isOS={isOS}
          onConfirm={handleDropConfirm}
          onClose={() => setDropTarget(null)}
        />
      )}
    </div>
  );
}

// ── KPI strip ─────────────────────────────────────────────────────────────────

function AssignKpiStrip({ rows, variant }) {
  const isOS = variant === "outreach";
  const totalPeople  = rows.length;
  const totalPending = rows.reduce((n, r) => n + r.pendingCount, 0);
  const totalActive  = rows.reduce((n, r) => n + r.active.length, 0);
  const idle         = rows.filter(r => r.pendingCount === 0 && r.active.length === 0).length;

  const k4 = isOS
    ? ["Interested", rows.reduce((n, r) => n + r.active.filter(i => i.status === "Interested").length, 0)]
    : ["At Stage 4",  rows.reduce((n, r) => n + r.active.filter(i => i.currentStage === 4).length, 0)];

  const totalCompleted = isOS ? null : rows.reduce((n, r) => n + (r.completed || 0), 0);

  const kpis = [
    [isOS ? "Specialists" : "Managers", totalPeople],
    ["Pending",  totalPending],
    ["Active",   totalActive],
    ...(!isOS ? [["Completed", totalCompleted]] : []),
    k4,
    ["Idle",     idle],
  ];

  return (
    <div style={{ display: "inline-flex", gap: 0, border: "1px solid var(--line)", borderRadius: 2 }}>
      {kpis.map(([l, v], i) => (
        <div key={i} style={{ padding: "6px 14px", borderRight: i < kpis.length - 1 ? "1px solid var(--line)" : "none" }}>
          <div className="text-mono text-xs text-mute" style={{ textTransform: "uppercase", letterSpacing: "0.1em" }}>{l}</div>
          <div className="text-mono" style={{ fontSize: 15, fontWeight: 500 }}>{v}</div>
        </div>
      ))}
    </div>
  );
}

function AssignKpi({ label, value, hot, last }) {
  return (
    <div style={{ padding: "4px 12px", borderRight: last ? "none" : "1px solid var(--line)", textAlign: "center", minWidth: 58 }}>
      <div className="text-mono" style={{ fontSize: 13, fontWeight: 600, color: hot ? "var(--alert-2)" : "var(--ink)" }}>{value}</div>
      <div className="text-mono text-xs text-mute" style={{ textTransform: "uppercase", letterSpacing: "0.08em" }}>{label}</div>
    </div>
  );
}

Object.assign(window, { AssignmentsPage });
