// StationArea — dotted-bordered container that replaces the previous per-
// station card. Two lanes:
//   AgentsRow   — idle pool of agent chips (one per station.agents entry NOT
//                 currently engaged on any task in this station)
//   TaskLane    — TaskCards filtered by task.area === station.id
// Plus an absolutely-positioned EngagedAgents layer (one chip per active
// assignment, perched above its assigned card) and a TetherLayer drawing
// short lines from each engaged chip down to its card.

const StationArea = ({ station, tasks, library, index, onOpenStation, onOpenTask, onOpenAgent, onDecision }) => {
  const AgentChip   = window.AgentChip;
  const TetherLayer = window.TetherLayer;
  const TaskCard    = window.TaskCard;
  const Bridge      = window.Bridge;
  const { colorFor, TOKENS } = window.AgentColors || {};

  const areaRef = React.useRef(null);
  // Refs keyed by taskId so TetherLayer can locate each card.
  const cardRefs = React.useRef({});
  // Refs keyed by `${agentId}::${taskId}` for engaged chips.
  const engagedChipRefs = React.useRef({});

  if (!AgentChip || !TetherLayer || !TaskCard || !colorFor) {
    return <div className="text-xs text-neutral-400">Loading station area…</div>;
  }

  const tasksHere = tasks.filter((t) => t.area === station.id);
  // An escalated task carries the orchestrator's instructions (validators
  // disagreed). It's a human moment distinct from awaitingApproval.
  const escalatedTask = tasksHere.find((t) => t.escalation);

  // Build engagement records from task.assigneeId. A task with no assigneeId
  // (queued / idle) contributes no engagement.
  const engagements = tasksHere
    .map((task) => {
      // Validator owns the task when the task is in 'validating' state.
      let owner = null;
      if (task.status === 'validating') {
        owner = Bridge?.primaryValidator(station) || null;
      } else if (task.status === 'working' || task.status === 'rejected') {
        owner = station.agents.find((a) => a.id === task.assigneeId) || null;
      }
      if (!owner) return null;
      // human-review state explicitly has NO chip docked
      if (task.status === 'human-review') return null;
      const colorName = colorFor(owner);
      return {
        taskId: task.id,
        agent: owner,
        hex: TOKENS[colorName]?.hex || '#d4d4d4',
        chipRef: { current: null },
        cardRef: cardRefs.current[task.id] || null,
      };
    })
    .filter(Boolean);

  // Idle agents = station.agents minus any agent currently engaged here.
  const engagedIds = new Set(engagements.map((e) => e.agent.id));
  const validator = Bridge?.primaryValidator(station) || null;
  const allAgentsInRow = [
    ...station.agents,
    ...(validator && !station.agents.find((a) => a.id === validator.id) ? [validator] : []),
  ];
  const idleAgents = allAgentsInRow.filter((a) => !engagedIds.has(a.id));

  // For each engagement, derive a borderColor token name to pass to TaskCard.
  const borderColorForTask = {};
  for (const eng of engagements) {
    borderColorForTask[eng.taskId] = colorFor(eng.agent);
  }

  return (
    <div
      ref={areaRef}
      className="relative border-2 border-dashed border-neutral-300 rounded-b-2xl p-4"
      style={{ minHeight: '216px' }}
    >
      {/* Station title */}
      <div className="flex items-center justify-between mb-3">
        <button
          type="button"
          onClick={() => onOpenStation && onOpenStation(station.id)}
          className="text-left"
        >
          <div className="text-[10px] font-bold uppercase tracking-widest text-neutral-400">
            Station {typeof index === 'number' ? index + 1 : ''}
          </div>
          <div className="text-base font-black text-neutral-800">{station.title}</div>
        </button>
        <div className="text-[10px] font-bold uppercase tracking-widest text-neutral-400">
          {tasksHere.length} active
        </div>
      </div>

      {/* Agents row — idle pool */}
      <div className="flex flex-wrap gap-2 mb-4 min-h-[36px]">
        {idleAgents.length === 0 && (
          <span className="text-[10px] uppercase tracking-widest text-neutral-300">All engaged</span>
        )}
        {idleAgents.map((a) => (
          <AgentChip
            key={`idle::${a.id}`}
            agent={a}
            state="idle"
            onOpen={onOpenAgent ? (agent) => onOpenAgent(agent, { station }) : null}
          />
        ))}
      </div>

      {/* Task lane — 2-column grid: tasks fill row-by-row, two per row.
          Rows flow downward as more tasks arrive. Each card carries its
          own actor pill above it (see TaskCard), so no separate
          engaged-chip overlay is needed. */}
      <div
        className="grid grid-cols-2 gap-3 justify-start"
        style={{ gridTemplateColumns: "repeat(2, 280px)" }}
      >
        {tasksHere.length === 0 ? (
          <div className="text-xs text-neutral-300 italic row-span-2">No tasks in this station</div>
        ) : (
          tasksHere.map((task) => {
            cardRefs.current[task.id] = cardRefs.current[task.id] || React.createRef();
            return (
              <div key={task.id} ref={cardRefs.current[task.id]}>
                <TaskCard
                  task={task}
                  station={station}
                  borderColor={borderColorForTask[task.id] || null}
                  onOpen={() => onOpenTask && onOpenTask(task.id)}
                  onOpenAgent={onOpenAgent}
                />
              </div>
            );
          })
        )}
      </div>

      {/* Escalation surface — the orchestrator escalated because the validators
          disagreed on a point the worker can't resolve. Shown independently of
          awaitingApproval; the user reads the instructions and decides a path. */}
      {escalatedTask?.escalation && (
        <div className="mt-3 p-3 rounded-lg bg-red-50 border border-red-200">
          <div className="text-xs font-bold uppercase tracking-widest text-red-700 mb-1">
            Validators disagreed — your call needed
          </div>
          <div className="text-xs text-red-800 whitespace-pre-wrap">
            {escalatedTask.escalation}
          </div>
        </div>
      )}

      {/* Approval UI — renders only when the orchestrator sets station.awaitingApproval
          (populated by Task 2.4). Dormant until then. */}
      {station.awaitingApproval && (
        <div className="mt-4 p-4 rounded-xl bg-amber-50 border border-amber-200">
          <div className="text-sm font-semibold text-amber-900 mb-2">
            Awaiting your approval — {station.stationId}
          </div>
          <div className="text-xs text-amber-800 mb-3">
            {station.awaitingApproval.deliverable?.summary || 'Review the deliverable above.'}
          </div>
          <div className="flex gap-2">
            <button
              className="px-3 py-1.5 text-xs font-semibold rounded-md bg-emerald-600 text-white hover:bg-emerald-700"
              onClick={async () => {
                await fetch(`/run/${station.runId}/approve`, {
                  method: 'POST',
                  headers: { 'Content-Type': 'application/json' },
                  body: JSON.stringify({ user: 'dalton' }),
                });
                // Fire-and-forget resume — kicks the walker on the server.
                // Don't await: /resume opens a long-running SSE stream.
                fetch(`/run/${station.runId}/resume`, {
                  method: 'POST',
                  headers: { 'Content-Type': 'application/json' },
                }).catch(() => {});
                onDecision?.();
              }}
            >{escalatedTask ? 'Acknowledge & continue' : 'Approve → next station'}</button>
            <button
              className="px-3 py-1.5 text-xs font-semibold rounded-md bg-sky-600 text-white hover:bg-sky-700"
              onClick={async () => {
                await fetch(`/run/${station.runId}/stop`, {
                  method: 'POST',
                  headers: { 'Content-Type': 'application/json' },
                  body: JSON.stringify({ user: 'dalton' }),
                });
                onDecision?.();
              }}
            >Approve → stop here</button>
            <button
              className="px-3 py-1.5 text-xs font-semibold rounded-md bg-red-600 text-white hover:bg-red-700"
              onClick={async () => {
                const reason = window.prompt('Reject reason?') || 'no reason given';
                await fetch(`/run/${station.runId}/reject`, {
                  method: 'POST',
                  headers: { 'Content-Type': 'application/json' },
                  body: JSON.stringify({ user: 'dalton', reason }),
                });
                onDecision?.();
              }}
            >Reject</button>
          </div>
        </div>
      )}
    </div>
  );
};

// EngagedAgentsLayer renders one absolutely-positioned chip per engagement.
// The chip's horizontal center is aligned with the center of its task card
// after layout via useLayoutEffect. Vertically pinned 8px above the card.
const EngagedAgentsLayer = ({ engagements, cardRefs, chipRefs, areaRef }) => {
  const AgentChip = window.AgentChip;
  const layerRef = React.useRef(null);

  React.useLayoutEffect(() => {
    const area = areaRef?.current;
    if (!area) return;
    const areaRect = area.getBoundingClientRect();
    for (const eng of engagements) {
      const key = `${eng.agent.id}::${eng.taskId}`;
      const chipWrap = chipRefs.current[key]?.current;
      const card = cardRefs.current[eng.taskId]?.current;
      if (!chipWrap || !card) continue;
      const cardRect = card.getBoundingClientRect();
      const cx = cardRect.left + cardRect.width / 2 - areaRect.left;
      const top = cardRect.top - areaRect.top - chipWrap.offsetHeight - 8;
      chipWrap.style.left = `${cx - chipWrap.offsetWidth / 2}px`;
      chipWrap.style.top = `${Math.max(0, top)}px`;
    }
  });

  return (
    <div ref={layerRef} className="absolute inset-0 pointer-events-none">
      {engagements.map((eng) => {
        const key = `${eng.agent.id}::${eng.taskId}`;
        chipRefs.current[key] = chipRefs.current[key] || React.createRef();
        return (
          <div
            key={key}
            ref={chipRefs.current[key]}
            className="absolute"
            style={{ left: 0, top: 0 }}
          >
            <AgentChip agent={eng.agent} state="engaged" taskId={eng.taskId} />
          </div>
        );
      })}
    </div>
  );
};

if (typeof window !== 'undefined') {
  window.StationArea = StationArea;
}
