// Pipeline Kanban — Variant A with drag-to-move support

const { useState: useStateA, useMemo: useMemoA, useRef: useRefA } = React;

function DraggableCandidateCard({ c, dense = true, onDragStart, onDragEnd, isDragging, onOpen, onRemind }) {
  const isStale = c.days >= 12 && !["hired","rejected","not_interested","declined","backburner"].includes(c.stage);
  return (
    <div
      draggable
      onClick={(e) => {
        // Only open if user didn't just finish dragging
        if (!isDragging) onOpen && onOpen(c.id);
      }}
      onDragStart={(e) => {
        e.dataTransfer.setData("text/candidate-id", c.id);
        e.dataTransfer.effectAllowed = "move";
        onDragStart && onDragStart(c.id);
      }}
      onDragEnd={() => onDragEnd && onDragEnd()}
      className={
        "ats-card" +
        (dense ? " ats-card--xdense" : "") +
        (c.flagged ? " is-flagged" : "") +
        (c.starred ? " is-starred" : "") +
        (isDragging ? " is-dragging" : "")
      }
    >
      <div className="ats-card__row">
        <Avatar src={c.avatar} name={c.name} size={dense ? 18 : 22} />
        <span className="ats-card__name">{c.name}</span>
        {c.duplicateIds && c.duplicateIds.length > 0 && (
          <span className="ats-card__dup" title={`${c.duplicateIds.length} duplicate profile${c.duplicateIds.length > 1 ? "s" : ""} found`}>
            <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
              <path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/>
              <line x1="12" y1="9" x2="12" y2="13"/>
              <line x1="12" y1="17" x2="12.01" y2="17"/>
            </svg>
          </span>
        )}
        {c.starred && <span className="ats-card__star">★</span>}
        <button
          className="ats-card__bell"
          title="Send reminder to DRI"
          onClick={(e) => { e.stopPropagation(); onRemind && onRemind(c.id); }}
          onMouseDown={(e) => e.stopPropagation()}
        >
          <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
            <path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9" strokeLinecap="round" strokeLinejoin="round"/>
            <path d="M10.3 21a1.94 1.94 0 0 0 3.4 0" strokeLinecap="round"/>
          </svg>
        </button>
        <span className="ats-card__grip" title="Drag to move">⋮⋮</span>
      </div>
      <div className="ats-card__row">
        <span className="ats-card__title">
          <b>{c.title.replace("Senior ","Sr ").replace("Research Scientist","Research Sci")}</b>
          <span style={{ color: "var(--fg-4)" }}> · </span>
          {c.company}
        </span>
      </div>
      <div className="ats-card__meta">
        <SourcePill source={c.source} />
        {c.duplicateIds && c.duplicateIds.length > 0 && <span className="ats-source-pill" data-src="duplicate">Duplicate</span>}
        <span className={"ats-card__days" + (isStale ? " is-stale" : "")}>{c.days}d</span>
        <span style={{ flex: 1 }} />
        <InitialDisc
          initials={c.recruiterInitials}
          color={c.recruiterColor}
          size={14}
          title={c.recruiterName}
        />
      </div>
    </div>
  );
}
// alias for back-compat
const CandidateCard = DraggableCandidateCard;

function KanbanColumn({ stage, candidates, onDragStart, onDragEnd, onDrop, draggingId, hoverStageId, onDragOver, onOpen, onRemind, onAdd, compact }) {
  const isTerminal = ["rejected","declined","hired","backburner"].includes(stage.id);
  const isHover = hoverStageId === stage.id && draggingId;
  return (
    <div
      className={"ats-col" + (isTerminal ? " ats-col--terminal" : "") + (compact ? " ats-col--compact" : "") + (isHover ? " is-drop-target" : "")}
      onDragOver={(e) => {
        e.preventDefault();
        e.dataTransfer.dropEffect = "move";
        onDragOver && onDragOver(stage.id);
      }}
      onDrop={(e) => {
        e.preventDefault();
        const id = e.dataTransfer.getData("text/candidate-id");
        if (id) onDrop && onDrop(id, stage.id);
      }}
    >
      <div className="ats-col__head">
        <div className="ats-col__title-line">
          {!compact && <span className="ats-col__dot" style={{ background: stage.accent }} />}
          <span className="ats-col__title">{stage.label}</span>
          <span className="ats-col__count">{candidates.length}</span>
        </div>
        {!compact && (
          <button className="ats-col__menu" title="More">
            <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"><circle cx="5" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="19" cy="12" r="1.6"/></svg>
          </button>
        )}
      </div>
      <div className="ats-col__body">
        {candidates.map(c => (
          <DraggableCandidateCard
            key={c.id}
            c={c}
            onDragStart={onDragStart}
            onDragEnd={onDragEnd}
            isDragging={draggingId === c.id}
            onOpen={onOpen}
            onRemind={onRemind}
          />
        ))}
        {candidates.length === 0 && (
          <div className={"ats-empty-hint" + (isHover ? " is-drop-hint" : "")}>
            {isHover ? "Drop to move here" : "Nothing here yet"}
          </div>
        )}
        {isHover && candidates.length > 0 && <div className="ats-col__drop-line" />}
      </div>
      {!isTerminal && !compact && (
        <button className="ats-col__add" onClick={() => onAdd && onAdd()}>＋ Add candidate</button>
      )}
    </div>
  );
}

function PipelineToolbar() {
  return (
    <div className="ats-toolbar">
      <div className="ats-toolbar__group">
        <button className="ats-btn ats-btn--ghost-bordered is-active">All open roles<span className="ats-btn__caret">▾</span></button>
        <button className="ats-btn">Stage <span className="ats-btn__caret">▾</span></button>
        <button className="ats-btn">Recruiter <span className="ats-btn__caret">▾</span></button>
        <button className="ats-btn">Source <span className="ats-btn__caret">▾</span></button>
      </div>
      <span className="ats-filter-chip">
        Stalled &gt; 7d <span className="ats-filter-chip__x">×</span>
      </span>
      <div className="ats-toolbar__spacer" />
      <div className="ats-toolbar__group">
        <button className="ats-btn">Group: Stage <span className="ats-btn__caret">▾</span></button>
        <button className="ats-btn">Sort: Days in stage <span className="ats-btn__caret">▾</span></button>
        <span className="ats-toolbar__divider" />
        <button className="ats-btn is-active">Kanban</button>
        <button className="ats-btn">Table</button>
        <button className="ats-btn">Calendar</button>
      </div>
    </div>
  );
}

function PipelineMetrics({ candidates, scopeLabel }) {
  // All metrics are derived from the candidates passed in, so they update
  // when the user filters by role / saved view in the sidebar.
  const active = candidates.filter(c => !["rejected","not_interested","declined","hired"].includes(c.stage));
  const inLoop = candidates.filter(c => ["intro","tech1","tech2","tech3","onsite","offer"].includes(c.stage));
  const offers = candidates.filter(c => c.stage === "offer");
  const sourcedThisWeek = candidates.filter(c => c.stage === "sourced" && c.days <= 7);
  const agencySourcesThisWeek = sourcedThisWeek.filter(c => ["jon","nick","techire","agency"].includes(c.source)).length;

  const roleCount = new Set(candidates.map(c => c.jobId)).size;

  // Scope-aware deltas — feel like real movement on the active scope, but
  // never imply more activity than there is data for.
  const weeklyDelta = Math.max(1, Math.round(active.length * 0.18));
  const onsiteCohort = candidates.filter(c => c.stage === "onsite");
  // Average days-in-stage for onsite candidates as a proxy for "time-to-onsite"
  const avgOnsite = onsiteCohort.length
    ? Math.round(onsiteCohort.reduce((s, c) => s + c.days, 0) / onsiteCohort.length) + 6
    : 14;

  // For the interview-loop subtitle, count distinct roles those candidates are on.
  const loopRoles = new Set(inLoop.map(c => c.jobId)).size;

  return (
    <div className="ats-metric-row">
      <div className="ats-metric">
        <div className="ats-metric__label">Active candidates</div>
        <div className="ats-metric__value">{active.length}</div>
        <div className="ats-metric__delta is-up">+{weeklyDelta} this week</div>
      </div>
      <div className="ats-metric">
        <div className="ats-metric__label">In interview loop</div>
        <div className="ats-metric__value">{inLoop.length}</div>
        <div className="ats-metric__delta">
          {loopRoles === 0 ? "—" : `across ${loopRoles} role${loopRoles === 1 ? "" : "s"}`}
        </div>
      </div>
      <div className="ats-metric">
        <div className="ats-metric__label">Offers extended</div>
        <div className="ats-metric__value">{offers.length}</div>
        <div className="ats-metric__delta is-up">
          {offers.length === 0 ? "none open" : `${offers.length} awaiting response`}
        </div>
      </div>
      <div className="ats-metric">
        <div className="ats-metric__label">Avg. time-to-onsite</div>
        <div className="ats-metric__value">{avgOnsite}<em style={{ fontSize: 14, color: "var(--fg-3)" }}>d</em></div>
        <div className="ats-metric__delta is-down">+2d vs last cycle</div>
      </div>
      <div className="ats-metric">
        <div className="ats-metric__label">Sourced this week</div>
        <div className="ats-metric__value">{sourcedThisWeek.length}</div>
        <div className="ats-metric__delta">
          {sourcedThisWeek.length === 0 ? "no new sources" : `${agencySourcesThisWeek} via agency`}
        </div>
      </div>
    </div>
  );
}

function PipelineKanban() {
  // Make candidates stateful so we can move them between columns
  const [candidates, setCandidates] = useStateA(() => CANDIDATES.map(c => ({ ...c })));
  React.useEffect(() => {
    const sync = () => setCandidates(prev => {
      return CANDIDATES.map(g => {
        const local = prev.find(p => p.id === g.id);
        return local ? { ...local, ...g } : { ...g };
      });
    });
    window.addEventListener("candidates-updated", sync);
    return () => window.removeEventListener("candidates-updated", sync);
  }, []);
  const [draggingId, setDraggingId] = useStateA(null);
  const [hoverStageId, setHoverStageId] = useStateA(null);
  const [toast, setToast] = useStateA(null);
  const [openCandidateId, setOpenCandidateId] = useStateA(null);
  const [addModalOpen, setAddModalOpen] = useStateA(false);
  const [, showToast, ToastHost] = useAtsToast();
  const [activeJob, setActiveJob] = useStateA(null);
  const handleSidebarSelect = (id) => {
    setActiveJob(id);
    const job = JOBS.find(j => j.id === id);
    if (job) showToast(`${job.title} — view filtered`);
    else if (id === "__all__") showToast("All roles");
    else if (id === null) showToast("All open roles");
    else showToast("Saved view selected");
  };

  const openCandidate = (id) => { setOpenCandidateId(id); window.location.hash = "candidate/" + id; };
  const closeModal = () => { setOpenCandidateId(null); history.replaceState(null, "", window.location.pathname + window.location.search); };

  const handleDrop = (id, stageId) => {
    const moved = candidates.find(c => c.id === id);
    setCandidates(prev => prev.map(c => {
      if (c.id !== id) return c;
      if (c.stage === stageId) return c;
      return { ...c, stage: stageId, days: 0, lastActivity: `Moved to ${STAGE_BY_ID[stageId].label} just now` };
    }));
    if (moved && moved.stage !== stageId) {
      setToast({
        name: moved.name,
        from: STAGE_BY_ID[moved.stage].label,
        to: STAGE_BY_ID[stageId].label,
      });
      setTimeout(() => setToast(null), 3500);
      updateCandidateStage(id, stageId);
    }
    setDraggingId(null);
    setHoverStageId(null);
  };

  return (
    <div className="ats-shell ats-shell--frame">
      <TopNav activeTab="Pipeline" />
      <div className="ats-body">
        <JobSidebar activeJobId={activeJob} onSelect={handleSidebarSelect} />
        <main className="ats-main">
          <div className="ats-page-head">
            <div>
              <h1 className="ats-page-title">
                Pipeline <em>—  all open roles</em>
              </h1>
              <div className="ats-page-sub">
                {candidates.length} candidates across {JOBS.length} roles · Last synced from LinkedIn 4 minutes ago · <span style={{ color: "var(--fg-2)" }}>Drag any card between columns to advance.</span>
              </div>
            </div>
            <div className="ats-page-actions">
              <button className="ats-btn ats-btn--ghost-bordered">Share view</button>
              <button className="ats-btn ats-btn--ghost-bordered">Automations · 4</button>
              <button className="ats-btn ats-btn--primary" onClick={() => setAddModalOpen(true)}>＋ Add candidate</button>
            </div>
          </div>
          <PipelineMetrics candidates={candidates} />
          <PipelineToolbar />
          <div className="ats-kanban">
            {STAGES.map(s => (
              <KanbanColumn
                key={s.id}
                stage={s}
                candidates={candidates.filter(c => c.stage === s.id)}
                onDragStart={setDraggingId}
                onDragEnd={() => { setDraggingId(null); setHoverStageId(null); }}
                onDrop={handleDrop}
                onDragOver={setHoverStageId}
                draggingId={draggingId}
                hoverStageId={hoverStageId}
                onOpen={openCandidate}
                onAdd={() => setAddModalOpen(true)}
              />
            ))}
          </div>
          {toast && (
            <div className="ats-toast">
              <span className="ats-toast__dot" />
              Moved <b>{toast.name}</b> from <span style={{ color: "var(--fg-3)" }}>{toast.from}</span> → <b>{toast.to}</b>
              <button className="ats-toast__undo">Undo</button>
            </div>
          )}
          {ToastHost}
        </main>
      </div>
      {openCandidateId && (
        <CandidateModal
          candidate={candidates.find(x => x.id === openCandidateId)}
          onClose={closeModal}
          onDelete={() => {
            setCandidates(prev => prev.filter(x => x.id !== openCandidateId));
            closeModal();
          }}
        />
      )}
      {addModalOpen && (
        <AddCandidateModal onClose={() => setAddModalOpen(false)} />
      )}
    </div>
  );
}

Object.assign(window, { CandidateCard, DraggableCandidateCard, KanbanColumn, PipelineKanban });
