"use client";
// Feature matrix: composable overlay-driven 2-tab layout.
// Matrix tab: overlay toggles control which visual layers render.
// Ops tab: probe status grid (unchanged from legacy).
import { useCallback, useMemo } from "react";
import { FeatureGrid } from "@/components/feature-grid";
import type { CellContext } from "@/components/feature-grid";
import { StatusTab } from "@/components/status-tab";
import { useLiveStatus } from "@/hooks/useLiveStatus";
import { useProbes, useTriggerProbe } from "@/hooks/use-probes";
import { mergeRowsToMap } from "@/lib/live-status";
import { useOverlays } from "@/hooks/useOverlays";
import { OverlayToggleBar } from "@/components/overlay-toggle-bar";
import { ComposedCell } from "@/components/composed-cell";
import { AdaptiveStatsBar } from "@/components/adaptive-stats-bar";
import { AdaptiveLegend } from "@/components/adaptive-legend";
import { ThemeToggle } from "@/components/theme-toggle";
import { BaselineTab } from "@/components/baseline-tab";
import type { ParityTier } from "@/components/parity-badge";
import { getDocsStatus } from "@/lib/docs-status";
import { deriveDepth } from "@/components/depth-utils";
import type { CatalogCell } from "@/components/depth-utils";
import type { DepthDistribution } from "@/components/adaptive-stats-bar";
import catalog from "@/data/catalog.json";
import type { CatalogData } from "@/data/catalog-types";

// Single cast: catalog.json is generated by `pretest`/`predev`/`prebuild` from
// generate-registry.ts and conforms to CatalogData by construction.
const catalogData: CatalogData = catalog as CatalogData;

export default function Page() {
  // Single subscription for ALL dimensions — no filter. Avoids the 7-way
  // SSE race that caused PB subscribe 400s when 7 hooks competed for the
  // single PB SDK realtime connection during hydration.
  const allStatus = useLiveStatus();

  const liveStatus = useMemo(
    () => mergeRowsToMap(allStatus.rows),
    [allStatus.rows],
  );

  const connection = allStatus.status;

  // R2-D.1: real probe wiring. `useProbes` polls the ops API every 10s and
  // feeds the schedule grid; `useTriggerProbe` POSTs to /trigger with the
  // operator token. If the token is unset, the trigger callback throws
  // a clear "token required" error from useTriggerProbe — fail-loud so
  // operators see the issue rather than a silent no-op.
  const probesQuery = useProbes();
  const probeEntries = useMemo(
    () => probesQuery.data?.probes ?? [],
    [probesQuery.data],
  );
  const triggerToken = process.env.NEXT_PUBLIC_OPS_TRIGGER_TOKEN;
  const { trigger } = useTriggerProbe({ token: triggerToken });
  const handleTrigger = useCallback(
    async (probeId: string, slugs?: string[]): Promise<void> => {
      await trigger(probeId, slugs);
    },
    [trigger],
  );

  // Overlay state management (handles URL hash + localStorage persistence)
  const {
    overlays,
    activeTab,
    toggle,
    applyPreset,
    setTab,
    activePreset,
    selectedProbeId,
    selectProbe,
  } = useOverlays();

  // Build a cell-lookup map: integration slug + feature id -> CatalogCell
  const cellLookup = useMemo(() => {
    const map = new Map<string, CatalogCell>();
    for (const cell of catalogData.cells) {
      if (cell.feature !== null) {
        map.set(`${cell.integration}:${cell.feature}`, cell);
      }
    }
    return map;
  }, []);

  // Compute health stats using the SAME color logic as the depth chips.
  // A cell's chip color depends on achieved vs maxPossible (from deriveDepth),
  // so the stats bar matches what's visually displayed in the table.
  const healthStats = useMemo(() => {
    let green = 0;
    let amber = 0;
    let red = 0;
    for (const cell of catalogData.cells) {
      if (cell.status !== "wired" || cell.feature === null) continue;
      const result = deriveDepth(cell as CatalogCell, liveStatus);
      if (result.unsupported) continue;
      const { achieved, maxPossible } = result;
      if (achieved === 0) {
        green++; // D0 = no probe data yet, not a failure
      } else if (achieved >= maxPossible) {
        green++; // At ceiling — same as green chip
      } else if (maxPossible - achieved <= 2) {
        amber++; // 1-2 below max — same as amber chip
      } else {
        red++; // 3+ below max — same as red chip
      }
    }
    return { green, amber, red };
  }, [liveStatus]);

  // Compute parity tier counts
  const parityStats = useMemo(() => {
    const counts: Record<ParityTier, number> = {
      reference: 0,
      at_parity: 0,
      partial: 0,
      minimal: 0,
      not_wired: 0,
    };
    // Count unique integrations by tier
    const seen = new Set<string>();
    for (const cell of catalogData.cells) {
      if (!seen.has(cell.integration)) {
        seen.add(cell.integration);
        counts[cell.parity_tier as ParityTier]++;
      }
    }
    return counts;
  }, []);

  // Compute docs reachability stats from unique feature IDs
  const docsStats = useMemo(() => {
    let ok = 0;
    let missing = 0;
    let notFound = 0;
    let error = 0;
    const seen = new Set<string>();
    for (const cell of catalogData.cells) {
      if (cell.feature !== null && !seen.has(cell.feature)) {
        seen.add(cell.feature);
        const status = getDocsStatus(cell.feature);
        if (status.og === "ok") ok++;
        else if (status.og === "missing") missing++;
        else if (status.og === "notfound") notFound++;
        else if (status.og === "error") error++;
      }
    }
    return { ok, missing, notFound, error };
  }, []);

  // Compute depth distribution across all wired cells — re-derives whenever
  // live-status changes since depth is a function of probe states.
  const depthDistribution = useMemo((): DepthDistribution => {
    const dist: DepthDistribution = {
      d5: 0,
      d4: 0,
      d3: 0,
      d2: 0,
      d1: 0,
      d0: 0,
    };
    for (const cell of catalogData.cells) {
      if (cell.status !== "wired" || cell.feature === null) continue;
      const result = deriveDepth(cell, liveStatus);
      if (result.unsupported) continue;
      const key = `d${result.achieved}` as keyof DepthDistribution;
      dist[key]++;
    }
    return dist;
  }, [liveStatus]);

  // renderCell callback wrapping ComposedCell
  const renderCell = useCallback(
    (ctx: CellContext) => {
      const catalogCell = cellLookup.get(
        `${ctx.integration.slug}:${ctx.feature.id}`,
      );
      return (
        <ComposedCell ctx={ctx} overlays={overlays} catalogCell={catalogCell} />
      );
    },
    [overlays, cellLookup],
  );

  return (
    <div data-testid="tab-shell" className="h-dvh flex flex-col">
      {/* Tab bar — pinned above scroll area */}
      <div className="flex-shrink-0 flex items-center gap-0 border-b border-[var(--border)] px-8">
        <button
          type="button"
          data-testid="tab-matrix"
          onClick={() => setTab("matrix")}
          className={`px-4 py-2.5 text-sm font-medium transition-colors cursor-pointer ${
            activeTab === "matrix"
              ? "text-[var(--accent)] border-b-2 border-[var(--accent)] -mb-px"
              : "text-[var(--text-muted)] hover:text-[var(--text-secondary)]"
          }`}
        >
          Coverage
        </button>
        <button
          type="button"
          data-testid="tab-baseline"
          onClick={() => setTab("baseline")}
          className={`px-4 py-2.5 text-sm font-medium transition-colors cursor-pointer ${
            activeTab === "baseline"
              ? "text-[var(--accent)] border-b-2 border-[var(--accent)] -mb-px"
              : "text-[var(--text-muted)] hover:text-[var(--text-secondary)]"
          }`}
        >
          Baseline
        </button>
        <button
          type="button"
          data-testid="tab-ops"
          onClick={() => setTab("ops")}
          className={`px-4 py-2.5 text-sm font-medium transition-colors cursor-pointer ${
            activeTab === "ops"
              ? "text-[var(--accent)] border-b-2 border-[var(--accent)] -mb-px"
              : "text-[var(--text-muted)] hover:text-[var(--text-secondary)]"
          }`}
        >
          Ops
        </button>
        <div className="ml-auto flex items-center pr-1">
          <ThemeToggle />
        </div>
      </div>

      {activeTab === "matrix" && (
        <>
          {/* Overlay toggle — pinned below tab bar */}
          <div className="flex-shrink-0 px-8 py-3 bg-[var(--bg-surface)] border-b border-[var(--border)]">
            <OverlayToggleBar
              overlays={overlays}
              onToggle={toggle}
              onApplyPreset={applyPreset}
              activePreset={activePreset}
            />
          </div>
          {/* Single scroll area — stats bar and title scroll away, table headers stick */}
          <div className="flex-1 min-h-0 overflow-auto pb-12">
            <div className="px-8 py-3 border-b border-[var(--border)]">
              <AdaptiveStatsBar
                overlays={overlays}
                catalog={catalogData}
                healthStats={healthStats}
                parityStats={parityStats}
                docsStats={docsStats}
                depthDistribution={depthDistribution}
              />
            </div>
            <FeatureGrid
              title="Feature Matrix"
              renderCell={renderCell}
              minColWidth={180}
              liveStatus={liveStatus}
              connection={connection}
              overlays={overlays}
              catalog={catalogData}
            />
            <AdaptiveLegend overlays={overlays} />
          </div>
        </>
      )}

      {activeTab === "baseline" && <BaselineTab />}

      {activeTab === "ops" && (
        <div className="flex-1 min-h-0 overflow-auto">
          <StatusTab
            entries={probeEntries}
            onTrigger={handleTrigger}
            selectedProbeId={selectedProbeId}
            onSelectProbe={selectProbe}
          />
        </div>
      )}
    </div>
  );
}
