/**
 * `TargetAnnouncementsOverlay` — F3 of ticket #4.
 *
 * Overlays the **target** agent's cell while another agent is talking to it: a
 * top banner ("un agent est en train de lui parler") and, below, its live
 * réflexions/annonces scrolling by. Mount/retract is driven by the target's
 * **busy** state (the single lifecycle authority — `agentBusyChanged` +
 * read-model hydration), so the overlay comes down at idle even when a turn ends
 * without any completion event. The announcements are its *content*.
 *
 * This is **not** a PTY block: the inter-agent contact runs on a separate
 * structured session. The overlay is a pure, non-interactive availability veil
 * (`pointer-events-none`) so it never traps focus or clicks.
 */

import { useEffect, useRef } from "react";

import { Spinner } from "@/shared";
import {
  useHydrateAgentBusy,
  useTargetAnnouncements,
} from "./AnnouncementsProvider";

export interface TargetAnnouncementsOverlayProps {
  /** Project hosting the agent (for read-model busy hydration at mount/reboot). */
  projectId: string;
  /** The agent whose cell this overlay guards (the announcement `target`). */
  agentId: string;
}

function formatTime(atMs: number): string {
  if (!Number.isFinite(atMs) || atMs <= 0) return "";
  try {
    return new Date(atMs).toLocaleTimeString();
  } catch {
    return "";
  }
}

export function TargetAnnouncementsOverlay({
  projectId,
  agentId,
}: TargetAnnouncementsOverlayProps) {
  // Seed busy from the reconciled read-model so a turn already in flight surfaces
  // when this cell mounts (reboot / late open); live events then take over.
  useHydrateAgentBusy(projectId, agentId);
  const { announcements, active } = useTargetAnnouncements(agentId);

  // Follow the tail as new announcements scroll in.
  const feedRef = useRef<HTMLDivElement>(null);
  useEffect(() => {
    const el = feedRef.current;
    if (el) el.scrollTop = el.scrollHeight;
  }, [announcements]);

  if (!active) return null;

  return (
    <div
      data-testid="target-announcements-overlay"
      role="status"
      aria-live="polite"
      className="pointer-events-none absolute inset-0 z-[4] flex flex-col bg-canvas/85 backdrop-blur-sm"
    >
      {/* ── Banner ── */}
      <div className="flex shrink-0 items-center gap-2 border-b border-border/60 bg-surface/80 px-4 py-2">
        <Spinner size={14} />
        <span className="text-sm font-medium text-content">
          Un agent est en train de lui parler…
        </span>
      </div>

      {/* ── Scrolling réflexions ── */}
      <div
        ref={feedRef}
        className="flex flex-1 flex-col justify-end gap-1.5 overflow-hidden px-6 py-4"
      >
        {announcements.map((a) => {
          const time = formatTime(a.atMs);
          return (
            <div
              key={a.seq}
              className="flex items-baseline gap-2 text-sm text-muted"
            >
              {time && <span className="shrink-0 text-xs text-faint">{time}</span>}
              <span className="whitespace-pre-wrap break-words text-content/90">
                {a.text}
              </span>
            </div>
          );
        })}
      </div>
    </div>
  );
}
