"use client";

import { useEffect, useRef, useState } from "react";

import { DataTable } from "@/components/data-table";
import { MetricCard } from "@/components/metric-card";
import { SectionHeading } from "@/components/section-heading";
import { SignalLineChart } from "@/components/line-chart";
import { StatusBadge } from "@/components/status-badge";
import {
  getCompositeDecomposition,
  getCompositeSignalLatest,
  getCompositeSignalSeries,
  getCompositeTransitions,
} from "@/lib/api/client";
import { formatMetricValue, formatTimestamp } from "@/lib/format";
import { DEFAULT_INITIAL_RANGE_DAYS, RANGE_OPTIONS, rangeWindowIso, seriesMaxPoints } from "@/lib/ranges";
import type {
  CompositeDecompositionResponse,
  CompositeSignalSeriesResponse,
  CompositeSignalSummary,
  CompositeTransitionResponse,
} from "@/lib/api/types";
import { useStream } from "@/lib/ws/use-stream";

import {
  COMPOSITE_DASHBOARDS,
  COMPOSITE_SIGNAL_LABELS,
  type CompositeDashboardConfig,
} from "./composite-config";

type TabId = "playbook" | "decomposition" | "transitions" | "rows";

function labelize(key: string) {
  return key.replace(/_/g, " ").replace(/\b\w/g, (match) => match.toUpperCase());
}

export function CompositeWorkspace({
  dashboardId,
  initialLatest,
  initialSeries,
  initialDecomposition,
  initialTransitions,
}: {
  dashboardId: string;
  initialLatest: CompositeSignalSummary | null;
  initialSeries: CompositeSignalSeriesResponse | null;
  initialDecomposition: CompositeDecompositionResponse | null;
  initialTransitions: CompositeTransitionResponse | null;
}) {
  const config = COMPOSITE_DASHBOARDS.find((item) => item.id === dashboardId) ?? COMPOSITE_DASHBOARDS[0];
  const [rangeDays, setRangeDays] = useState(DEFAULT_INITIAL_RANGE_DAYS);
  const [quality, setQuality] = useState("all");
  const [latest, setLatest] = useState(initialLatest);
  const [series, setSeries] = useState(initialSeries);
  const [decomposition, setDecomposition] = useState(initialDecomposition);
  const [transitions, setTransitions] = useState(initialTransitions);
  const [fetching, setFetching] = useState(false);
  const [activeTab, setActiveTab] = useState<TabId>(
    dashboardId === "composite_decomposition" ? "decomposition" : "playbook",
  );
  const refreshAbortRef = useRef<AbortController | null>(null);
  const refreshInFlightRef = useRef(false);
  const pendingRefreshRef = useRef(false);

  useStream((event) => {
    if (event.event === "dataset.updated" || event.event === "signal.updated" || event.event === "run.updated") {
      void refresh();
    }
  });

  useEffect(() => {
    void refresh();
  }, [dashboardId, rangeDays, quality]);

  async function refresh() {
    if (refreshInFlightRef.current) {
      pendingRefreshRef.current = true;
      return;
    }
    refreshAbortRef.current?.abort();
    const controller = new AbortController();
    refreshAbortRef.current = controller;
    refreshInFlightRef.current = true;
    setFetching(true);
    try {
      const nextLatest = await getCompositeSignalLatest(config.signalId, controller.signal);
      const { start, end } = rangeWindowIso(rangeDays, nextLatest?.latest_updated_at ?? latest?.latest_updated_at);
      const [nextSeries, nextDecomposition, nextTransitions] = await Promise.all([
        getCompositeSignalSeries(
          config.signalId,
          start,
          end,
          quality === "all" ? undefined : quality,
          seriesMaxPoints(rangeDays),
          controller.signal,
        ),
        getCompositeDecomposition(
          config.signalId,
          start,
          end,
          quality === "all" ? undefined : quality,
          seriesMaxPoints(rangeDays),
          controller.signal,
        ),
        getCompositeTransitions(
          config.signalId,
          start,
          end,
          quality === "all" ? undefined : quality,
          seriesMaxPoints(rangeDays),
          controller.signal,
        ),
      ]);
      if (!controller.signal.aborted) {
        setLatest(nextLatest);
        setSeries(nextSeries);
        setDecomposition(nextDecomposition);
        setTransitions(nextTransitions);
      }
    } finally {
      if (refreshAbortRef.current === controller) {
        refreshAbortRef.current = null;
      }
      refreshInFlightRef.current = false;
      setFetching(false);
      if (pendingRefreshRef.current) {
        pendingRefreshRef.current = false;
        void refresh();
      }
    }
  }

  const chartData = (series?.points ?? []).map((point) => ({
    ts: point.ts,
    ...point.values,
  }));

  const rows = (series?.points ?? []).slice(-12).reverse().map((point) => ({
    ts: formatTimestamp(point.ts),
    sentiment_index: point.values.sentiment_index,
    directional_tilt: point.values.directional_tilt,
    fragility_index: point.values.fragility_index,
    confidence_score: point.values.confidence_score,
    quality_flag: point.quality_flag ?? "unknown",
  }));

  const contributorRows = (decomposition?.latest_contributors ?? []).map((record) => ({
    pillar: record.pillar,
    family: record.family,
    component: record.component,
    normalized_value: record.normalized_value,
    signed_contribution: record.signed_contribution,
    quality_flag: record.quality_flag ?? "unknown",
  }));

  const transitionRows = (transitions?.records ?? []).map((record) => ({
    ts: formatTimestamp(record.ts),
    index_type: record.index_type,
    current_regime: record.current_regime ?? "—",
    prior_regime: record.prior_regime ?? "—",
    stay_probability: record.stay_probability,
    upshift_probability: record.upshift_probability,
    downshift_probability: record.downshift_probability,
    median_regime_duration_hours: record.median_regime_duration_hours,
    quality_flag: record.quality_flag ?? "unknown",
  }));

  return (
    <div className="pageStack">
      <SectionHeading
        kicker="Composite"
        title={`${config.title} workspace`}
        description={config.description}
      />
      <div className="twoCol">
        <div className="twoColNarrow">
          <div className="panel">
            <div className="toolbar" style={{ flexDirection: "column", alignItems: "stretch", gap: 8 }}>
              <label>
                Range
                <select value={rangeDays} onChange={(event) => setRangeDays(Number(event.target.value))}>
                  {RANGE_OPTIONS.map((days) => (
                    <option key={days} value={days}>{days}d</option>
                  ))}
                </select>
              </label>
              <label>
                Quality
                <select value={quality} onChange={(event) => setQuality(event.target.value)}>
                  <option value="all">all</option>
                  <option value="ok">ok</option>
                  <option value="partial_context">partial_context</option>
                  <option value="insufficient_data">insufficient_data</option>
                </select>
              </label>
            </div>
          </div>
          <StatusBadge label={fetching ? "LOADING" : "READY"} tone={fetching ? "neutral" : "ok"} />
          <div style={{ display: "flex", flexDirection: "column", gap: 0 }}>
            {Object.entries(latest?.latest_values ?? {})
              .filter(([key]) => key in COMPOSITE_SIGNAL_LABELS)
              .slice(0, 4)
              .map(([key, value]) => (
                <MetricCard
                  key={key}
                  label={COMPOSITE_SIGNAL_LABELS[key] ?? labelize(key)}
                  value={typeof value === "number" ? formatMetricValue(value, key) : String(value ?? "—")}
                  tone={latest?.latest_quality === "ok" ? "ok" : "warn"}
                />
              ))}
          </div>
          <div className="panel">
            <div className="panelHeader"><h3>Regimes</h3></div>
            <ul className="summaryList">
              <li><span>Sentiment</span><strong>{latest?.latest_values.sentiment_regime ? String(latest.latest_values.sentiment_regime) : "—"}</strong></li>
              <li><span>Directional</span><strong>{latest?.latest_values.directional_regime ? String(latest.latest_values.directional_regime) : "—"}</strong></li>
              <li><span>Fragility</span><strong>{latest?.latest_values.fragility_regime ? String(latest.latest_values.fragility_regime) : "—"}</strong></li>
            </ul>
          </div>
        </div>
        <div className="twoColWide">
          <SignalLineChart data={chartData} lines={config.lines} dualAxis />
          <div className="tabBar">
            <button className={`tabItem ${activeTab === "playbook" ? "tabActive" : ""}`} onClick={() => setActiveTab("playbook")}>Playbook</button>
            <button className={`tabItem ${activeTab === "decomposition" ? "tabActive" : ""}`} onClick={() => setActiveTab("decomposition")}>Decomposition</button>
            <button className={`tabItem ${activeTab === "transitions" ? "tabActive" : ""}`} onClick={() => setActiveTab("transitions")}>Transitions</button>
            <button className={`tabItem ${activeTab === "rows" ? "tabActive" : ""}`} onClick={() => setActiveTab("rows")}>Rows</button>
          </div>
          {activeTab === "playbook" && <PlaybookPanel config={config} />}
          {activeTab === "decomposition" && (
            <div className="panel">
              <div className="panelHeader"><h3>Top contributors</h3></div>
              <DataTable
                columns={["pillar", "family", "component", "normalized_value", "signed_contribution", "quality_flag"]}
                rows={contributorRows}
                statusColumn="quality_flag"
              />
            </div>
          )}
          {activeTab === "transitions" && (
            <DataTable
              columns={[
                "ts",
                "index_type",
                "current_regime",
                "prior_regime",
                "stay_probability",
                "upshift_probability",
                "downshift_probability",
                "median_regime_duration_hours",
                "quality_flag",
              ]}
              rows={transitionRows}
              statusColumn="quality_flag"
            />
          )}
          {activeTab === "rows" && (
            <DataTable
              columns={config.tableColumns}
              rows={rows}
              statusColumn="quality_flag"
            />
          )}
        </div>
      </div>
    </div>
  );
}

function PlaybookPanel({ config }: { config: CompositeDashboardConfig }) {
  return (
    <div className="playbookPanel">
      <p style={{ color: "var(--muted)", fontSize: 12 }}>{config.playbook.whatItMeasures}</p>
      <PlaybookList title="Interpretation" items={config.playbook.interpretation} />
      <PlaybookList title="Trade expressions" items={config.playbook.tradeExpressions} />
      <PlaybookList title="Caveats" items={config.playbook.caveats} />
      <PlaybookList title="Check next" items={config.playbook.companionChecks} />
    </div>
  );
}

function PlaybookList({ title, items }: { title: string; items: string[] }) {
  return (
    <div className="playbookSection">
      <p className="eyebrow">{title}</p>
      <ul className="playbookList">
        {items.map((item) => (
          <li key={item}>{item}</li>
        ))}
      </ul>
    </div>
  );
}
