/**
 * ViewerShell — the centre pane.
 *
 * Hosts the viewer adapter (currently the T02 PDF spike) and shows whatever
 * is active. `work/` consumes only the adapter's public surface
 * (`PdfSpikeViewer`) — it never touches PDF.js or react-pdf-highlighter-plus
 * directly. When the PDF library is swapped (or the spike is replaced),
 * only the adapter module changes; this shell stays the same.
 *
 * The annotation toolbar lived here in earlier iterations; CE-WP-0005-iter4
 * moved it into the evidence sidebar so the capture form appears in the
 * sidebar's document-flow position. The viewer now only renders the PDF
 * and surfaces the activate/click events.
 */

import { useCallback, useMemo } from "react";
import { PdfSpikeViewer, type StoredAnnotation } from "@anchor/index";
import { resolvePdfViewerUrl } from "@source/pdf/viewer-url";
import type { AnnotationId } from "@shared/ids";
import {
  useActiveDocument,
  useEngine,
  useEngineEventTick,
  useLastActivatedEvidence,
  usePendingSelection,
  usePdfByteStore,
  useScrollToAnnotation,
} from "./EngineContext";
import { useDebugFlag } from "./useDebugFlags";

export function ViewerShell() {
  const engine = useEngine();
  const byteStore = usePdfByteStore();
  const { document, representation } = useActiveDocument();
  const { set: setPending } = usePendingSelection();
  const { id: scrollToId, version: scrollVersion, scrollTo } = useScrollToAnnotation();
  const [debugTextLayer] = useDebugFlag("textLayer");
  const [hideCanvas] = useDebugFlag("hideCanvas");
  const [hideTextLayer] = useDebugFlag("hideTextLayer");
  const [hideAnnotationLayer] = useDebugFlag("hideAnnotationLayer");
  const [hideXfaLayer] = useDebugFlag("hideXfaLayer");
  const activeEvidenceId = useLastActivatedEvidence();

  // The viewer needs to re-fetch its highlight list whenever annotations
  // change. The tick is included in the memo deps so the list re-resolves.
  const annotationTick = useEngineEventTick("AnnotationCreated");
  const annotationUpdateTick = useEngineEventTick("AnnotationUpdated");

  const annotations = useMemo<StoredAnnotation[]>(() => {
    if (!document) return [];
    return engine.annotations.listByDocument(document.id).map((a) => ({
      id: a.id,
      text: a.quote ?? "",
      selectors: a.selectors,
    }));
  }, [document, engine, annotationTick, annotationUpdateTick]);

  // The annotation id that visually represents the "active" focus —
  // derived from the active evidence's first annotation.
  const activeAnnotationId = useMemo<AnnotationId | null>(() => {
    if (!activeEvidenceId) return null;
    const item = engine.evidence.get(activeEvidenceId);
    return item?.annotationIds[0] ?? null;
  }, [activeEvidenceId, engine]);

  const fileUrl = useMemo(() => {
    if (!document) return null;
    return resolvePdfViewerUrl(document, byteStore);
  }, [document, byteStore]);

  const scrollRequestKey =
    scrollToId !== null ? `${scrollToId}:${scrollVersion}` : null;

  const handleHighlightClicked = useCallback(
    (annotationId: string) => {
      if (!document) return;
      const item = engine.evidence.findByAnnotationId(
        document.id,
        annotationId as AnnotationId,
      );
      if (!item) return;
      engine.evidence.activate(item.id, "citation-card");
      // Re-trigger scroll so a click on the highlight also keeps it
      // centred in the viewport.
      scrollTo(annotationId as AnnotationId);
    },
    [document, engine, scrollTo],
  );

  if (!document || !representation || !fileUrl) {
    return (
      <main
        style={{
          flex: 1,
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          color: "#666",
          fontFamily: "system-ui, sans-serif",
        }}
      >
        Upload a PDF on the left to begin.
      </main>
    );
  }

  return (
    <main
      style={{
        flex: 1,
        display: "flex",
        flexDirection: "column",
        overflow: "hidden",
        position: "relative",
      }}
    >
      <div style={{ flex: 1, overflow: "hidden", position: "relative" }}>
        <PdfSpikeViewer
          // Re-key on document + debug flags only — scroll requests must
          // not remount the viewer (that re-fetches the PDF blob).
          key={[
            document.id,
            debugTextLayer ? "d" : "n",
            hideCanvas ? "hc" : "",
            hideTextLayer ? "ht" : "",
            hideAnnotationLayer ? "ha" : "",
            hideXfaLayer ? "hx" : "",
          ].join("#")}
          pdfUrl={fileUrl}
          storedAnnotations={annotations}
          {...(scrollToId ? { scrollToAnnotationId: scrollToId } : {})}
          {...(scrollRequestKey ? { scrollRequestKey } : {})}
          activeAnnotationId={activeAnnotationId}
          onHighlightClicked={handleHighlightClicked}
          debugTextLayer={debugTextLayer}
          hideCanvas={hideCanvas}
          hideTextLayer={hideTextLayer}
          hideAnnotationLayer={hideAnnotationLayer}
          hideXfaLayer={hideXfaLayer}
          onSelectionCaptured={(capture, selectors) => {
            setPending({ capture, selectors });
          }}
        />
      </div>
    </main>
  );
}
