"use client";

import { FormEvent, Suspense, startTransition, useCallback, useEffect, useMemo, useRef, useState } from "react";
import Image from "next/image";
import { useRouter, useSearchParams } from "next/navigation";
import { AppShell } from "@/components/prism/AppShell";
import { ChartCard } from "@/components/prism/ChartCard";
import { KPIStrip } from "@/components/prism/KPIStrip";
import { Sidebar } from "@/components/prism/Sidebar";
import { TickerHeader } from "@/components/prism/TickerHeader";
import { TopBar } from "@/components/prism/TopBar";
import { ApiError, api } from "@/lib/api";
import { deltaClass, fmtCurrency, fmtLarge, fmtNumber, fmtPct } from "@/lib/format";
import { availableFieldSummary, buildKpis, limitIndices, marketClock, OVERVIEW_NAV_ITEMS, signalTone, unavailableFields } from "@/lib/overview";
import type { HistoryPoint, MarketIndex, SearchResult, TickerOverview, WatchlistResponse } from "@/types/api";

type LoadState = "idle" | "loading" | "ready" | "invalid" | "error";
type ChartState = "idle" | "loading" | "ready" | "error";

export default function OverviewPage() {
  return (
    <Suspense fallback={<LoadingShell />}>
      <OverviewClient />
    </Suspense>
  );
}

function OverviewClient() {
  const router = useRouter();
  const searchParams = useSearchParams();
  const selectedTicker = (searchParams.get("ticker") || "").toUpperCase();
  const lastTickerRef = useRef("");

  const [query, setQuery] = useState("");
  const [results, setResults] = useState<SearchResult[]>([]);
  const [searching, setSearching] = useState(false);
  const [market, setMarket] = useState<MarketIndex[]>([]);
  const [overview, setOverview] = useState<TickerOverview | null>(null);
  const [history, setHistory] = useState<HistoryPoint[]>([]);
  const [watchlist, setWatchlist] = useState<WatchlistResponse>({ items: [], limit: 10 });
  const [period, setPeriod] = useState("1y");
  const [overviewState, setOverviewState] = useState<LoadState>("idle");
  const [overviewError, setOverviewError] = useState<string | null>(null);
  const [chartState, setChartState] = useState<ChartState>("idle");
  const [chartError, setChartError] = useState<string | null>(null);
  const [watchlistError, setWatchlistError] = useState<string | null>(null);
  const [clockSnapshot, setClockSnapshot] = useState(() => marketClock());

  const watchlistSymbols = useMemo(() => new Set(watchlist.items.map((item) => item.symbol)), [watchlist]);
  const isSaved = selectedTicker ? watchlistSymbols.has(selectedTicker) : false;
  const marketCards = useMemo(() => limitIndices(market), [market]);
  const kpis = useMemo(() => (overview ? buildKpis(overview) : []), [overview]);
  const missingFields = useMemo(() => (overview ? unavailableFields(overview) : []), [overview]);

  useEffect(() => {
    const timer = window.setInterval(() => setClockSnapshot(marketClock()), 60_000);
    return () => window.clearInterval(timer);
  }, []);

  const navigateToTicker = useCallback(
    (symbol: string) => {
      const normalized = symbol.trim().toUpperCase();
      if (!normalized) return;

      setResults([]);
      setQuery("");
      setOverview(null);
      setHistory([]);
      setOverviewError(null);
      setChartError(null);
      setWatchlistError(null);
      setOverviewState("loading");
      setChartState("loading");

      startTransition(() => {
        router.push(`/?ticker=${encodeURIComponent(normalized)}`);
      });
    },
    [router]
  );

  const clearTicker = useCallback(() => {
    setOverview(null);
    setHistory([]);
    setOverviewError(null);
    setChartError(null);
    setWatchlistError(null);
    setOverviewState("idle");
    setChartState("idle");
    startTransition(() => {
      router.push("/");
    });
  }, [router]);

  const refreshWatchlist = useCallback(async () => {
    try {
      setWatchlist(await api.watchlist());
    } catch {
      setWatchlist({ items: [], limit: 10 });
    }
  }, []);

  useEffect(() => {
    api.marketIndices().then(setMarket).catch(() => setMarket([]));
    refreshWatchlist();
  }, [refreshWatchlist]);

  useEffect(() => {
    if (query.trim().length < 2) {
      setResults([]);
      setSearching(false);
      return;
    }

    let cancelled = false;
    setSearching(true);

    const timer = window.setTimeout(() => {
      api
        .search(query)
        .then((rows) => {
          if (!cancelled) setResults(rows);
        })
        .catch(() => {
          if (!cancelled) setResults([]);
        })
        .finally(() => {
          if (!cancelled) setSearching(false);
        });
    }, 250);

    return () => {
      cancelled = true;
      window.clearTimeout(timer);
    };
  }, [query]);

  useEffect(() => {
    if (!selectedTicker) {
      lastTickerRef.current = "";
      setOverview(null);
      setHistory([]);
      setOverviewError(null);
      setChartError(null);
      setOverviewState("idle");
      setChartState("idle");
      return;
    }

    if (lastTickerRef.current === selectedTicker) return;

    let cancelled = false;
    lastTickerRef.current = selectedTicker;
    setOverviewState("loading");
    setOverviewError(null);
    setOverview(null);

    api
      .overview(selectedTicker)
      .then((overviewData) => {
        if (cancelled) return;
        setOverview(overviewData);
        setOverviewState("ready");
      })
      .catch((exc: Error) => {
        if (cancelled) return;
        setOverview(null);
        setChartState("idle");
        setHistory([]);

        if (exc instanceof ApiError && exc.status === 404) {
          setOverviewState("invalid");
          setOverviewError("Ticker not found");
          return;
        }

        setOverviewState("error");
        setOverviewError(exc.message || "Ticker data unavailable");
      });

    return () => {
      cancelled = true;
    };
  }, [selectedTicker]);

  useEffect(() => {
    if (!selectedTicker) return;

    let cancelled = false;
    setChartState("loading");
    setChartError(null);
    setHistory([]);

    api
      .history(selectedTicker, period)
      .then((historyData) => {
        if (cancelled) return;
        setHistory(historyData);
        setChartState("ready");
      })
      .catch((exc: Error) => {
        if (cancelled) return;
        setHistory([]);
        setChartState("error");
        setChartError(exc.message || "Could not load chart history");
      });

    return () => {
      cancelled = true;
    };
  }, [selectedTicker, period]);

  async function onSearchSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (results[0]) {
      navigateToTicker(results[0].symbol);
      return;
    }
    if (query.trim()) navigateToTicker(query);
  }

  async function addOrRemoveCurrentTicker() {
    if (!selectedTicker) return;
    try {
      const next = isSaved ? await api.removeWatchlist(selectedTicker) : await api.addWatchlist(selectedTicker);
      setWatchlist(next);
      setWatchlistError(null);
    } catch (exc) {
      setWatchlistError(exc instanceof Error ? exc.message : "Could not update watchlist");
    }
  }

  async function removeFromWatchlist(symbol: string) {
    try {
      const next = await api.removeWatchlist(symbol);
      setWatchlist(next);
      setWatchlistError(null);
    } catch (exc) {
      setWatchlistError(exc instanceof Error ? exc.message : "Could not update watchlist");
    }
  }

  const shell = (
    <AppShell
      sidebar={
        <Sidebar
          navItems={OVERVIEW_NAV_ITEMS}
          selectedKey="overview"
          currentTicker={selectedTicker}
          watchlist={watchlist}
          watchlistError={watchlistError}
          onSelectTicker={navigateToTicker}
          onRemoveTicker={removeFromWatchlist}
        />
      }
      topbar={
        <TopBar
          query={query}
          searching={searching}
          results={results}
          marketStatus={clockSnapshot}
          onChangeQuery={setQuery}
          onSubmit={onSearchSubmit}
          onSelectTicker={navigateToTicker}
        />
      }
    >
      <MarketStrip indices={marketCards} />
      {!selectedTicker ? <EmptyOverviewState watchlist={watchlist} onSelectTicker={navigateToTicker} /> : null}
      {selectedTicker && overviewState === "loading" ? <LoadingOverviewState symbol={selectedTicker} /> : null}
      {selectedTicker && overviewState === "invalid" ? <InvalidTickerState symbol={selectedTicker} onClear={clearTicker} /> : null}
      {selectedTicker && overviewState === "error" ? <ErrorOverviewState message={overviewError || "Ticker data unavailable"} /> : null}
      {overview && overviewState === "ready" ? (
        <>
          <TickerHeader overview={overview} onToggleWatchlist={addOrRemoveCurrentTicker} isSaved={isSaved} />
          <KPIStrip items={kpis} />
          <div className="psm-main-grid">
            <div className="psm-column">
              <ChartCard symbol={overview.profile.symbol} period={period} points={history} chartState={chartState} chartError={chartError} onChangePeriod={setPeriod} />
              <SignalCard overview={overview} />
            </div>
            <div className="psm-column">
              <DataStatusCard overview={overview} missingFields={missingFields} />
              <ProfileCard overview={overview} />
              <ShortInterestCard overview={overview} />
              <StatsCard overview={overview} />
            </div>
          </div>
        </>
      ) : null}
    </AppShell>
  );

  return shell;
}

function MarketStrip({ indices }: { indices: MarketIndex[] }) {
  if (!indices.length) {
    return <section className="psm-card-empty psm-market-card">Market data is temporarily unavailable.</section>;
  }

  return (
    <section className="psm-market-strip" aria-label="Market indices">
      {indices.map((index) => (
        <article key={index.name} className="psm-market-card">
          <span className="psm-market-name">{index.name}</span>
          <span className="psm-market-price">{fmtNumber(index.price)}</span>
          <span className={`psm-market-change ${deltaClass(index.change_pct)}`}>{fmtPct(index.change_pct, 2, true)}</span>
        </article>
      ))}
    </section>
  );
}

function EmptyOverviewState({ watchlist, onSelectTicker }: { watchlist: WatchlistResponse; onSelectTicker: (symbol: string) => void }) {
  return (
    <section className="psm-state-panel">
      <div className="psm-state-title">Overview</div>
      <h1>Choose a ticker to enter the workbench.</h1>
      <p>Search from the top bar or jump into one of your saved symbols from the sidebar watchlist.</p>
      {watchlist.items.length ? (
        <div className="psm-stack">
          {watchlist.items.map((item) => (
            <button key={item.symbol} type="button" className="psm-ghost-action" onClick={() => onSelectTicker(item.symbol)}>
              {item.symbol}
            </button>
          ))}
        </div>
      ) : null}
    </section>
  );
}

function LoadingOverviewState({ symbol }: { symbol: string }) {
  return (
    <div className="psm-loading-shell">
      <section className="psm-state-panel">
        <div className="psm-state-title">Loading</div>
        <h1>{symbol}</h1>
        <p>Fetching quote, profile, signals, and supporting metrics.</p>
      </section>
      <section className="psm-card psm-skeleton" />
      <section className="psm-card psm-skeleton" />
    </div>
  );
}

function InvalidTickerState({ symbol, onClear }: { symbol: string; onClear: () => void }) {
  return (
    <section className="psm-state-panel">
      <span className="psm-status-chip invalid">Invalid Ticker</span>
      <h1>{symbol}</h1>
      <p>This symbol could not be resolved into usable market data. Try another search or return to the empty workspace.</p>
      <button type="button" className="psm-ghost-action" onClick={onClear}>
        Clear Selection
      </button>
    </section>
  );
}

function ErrorOverviewState({ message }: { message: string }) {
  return (
    <section className="psm-state-panel">
      <span className="psm-status-chip invalid">Data Error</span>
      <h1>Overview unavailable</h1>
      <p>{message}</p>
    </section>
  );
}

function SignalCard({ overview }: { overview: TickerOverview }) {
  return (
    <section className="psm-card">
      <div className="psm-card-head">
        <div>
          <div className="psm-eyebrow">Signals</div>
          <h2 className="psm-card-title">Readthrough</h2>
        </div>
      </div>
      <div className="psm-signal-grid">
        {overview.signals.map((signal) => (
          <article key={signal.key} className={`psm-signal ${signalTone(signal.state)}`}>
            <span className="psm-signal-key">{signal.key}</span>
            <span className="psm-signal-value">{signal.value}</span>
            <span className="psm-signal-copy">{signal.description}</span>
          </article>
        ))}
      </div>
    </section>
  );
}

function DataStatusCard({ overview, missingFields }: { overview: TickerOverview; missingFields: string[] }) {
  const entries = Object.entries(overview.meta.sources).slice(0, 6);

  return (
    <section className="psm-card">
      <div className="psm-card-head">
        <div>
          <div className="psm-eyebrow">Data Quality</div>
          <h2 className="psm-card-title">Coverage</h2>
        </div>
        <span className={`psm-status-chip${overview.meta.is_partial ? " partial" : ""}`}>{overview.meta.status}</span>
      </div>
      <p className="psm-quality-copy">{availableFieldSummary(overview)}</p>
      {overview.meta.is_partial ? (
        <div className="psm-stack">
          {missingFields.length ? missingFields.slice(0, 8).map((field) => <span key={field} className="psm-field-tag missing">{field}</span>) : null}
        </div>
      ) : null}
      <div className="psm-source-list">
        {entries.length ? (
          entries.map(([field, source]) => (
            <div className="psm-source-row" key={field}>
              <span className="psm-source-key">{field}</span>
              <span className="psm-source-value">{source}</span>
            </div>
          ))
        ) : (
          <div className="psm-source-row">
            <span className="psm-source-key">Sources</span>
            <span className="psm-source-value">Unavailable</span>
          </div>
        )}
      </div>
    </section>
  );
}

function ProfileCard({ overview }: { overview: TickerOverview }) {
  return (
    <section className="psm-card">
      <div className="psm-card-head">
        <div>
          <div className="psm-eyebrow">Company Profile</div>
          <h2 className="psm-card-title">Context</h2>
        </div>
      </div>
      <div className="psm-profile-list">
        <div className="psm-profile-row">
          <span className="psm-profile-key">Sector</span>
          <span className="psm-profile-value">{overview.profile.sector || "Unavailable"}</span>
        </div>
        <div className="psm-profile-row">
          <span className="psm-profile-key">Industry</span>
          <span className="psm-profile-value">{overview.profile.industry || "Unavailable"}</span>
        </div>
        <div className="psm-profile-row">
          <span className="psm-profile-key">Exchange</span>
          <span className="psm-profile-value">{overview.profile.exchange || "Unavailable"}</span>
        </div>
        <div className="psm-profile-row">
          <span className="psm-profile-key">Website</span>
          <span className="psm-profile-value">
            {overview.profile.website ? (
              <a href={overview.profile.website} target="_blank" rel="noreferrer" className="psm-link">
                {overview.profile.website}
              </a>
            ) : (
              "Unavailable"
            )}
          </span>
        </div>
      </div>
      <p className="psm-profile-summary">{overview.profile.summary || "Business summary unavailable."}</p>
    </section>
  );
}

function ShortInterestCard({ overview }: { overview: TickerOverview }) {
  const short = overview.short_interest;
  return (
    <section className="psm-card">
      <div className="psm-card-head">
        <div>
          <div className="psm-eyebrow">Short Interest</div>
          <h2 className="psm-card-title">Pressure</h2>
        </div>
      </div>
      <div className="psm-detail-grid">
        <DetailItem label="Short Float" value={fmtPct(short.short_percent_of_float)} missing={short.short_percent_of_float == null} />
        <DetailItem label="Days Cover" value={fmtNumber(short.short_ratio)} missing={short.short_ratio == null} />
        <DetailItem label="Shares Short" value={fmtNumber(short.shares_short, 0)} missing={short.shares_short == null} />
        <DetailItem label="Prior Delta" value={fmtPct(short.shares_short_delta_pct, 1, true)} missing={short.shares_short_delta_pct == null} />
      </div>
    </section>
  );
}

function StatsCard({ overview }: { overview: TickerOverview }) {
  return (
    <section className="psm-card">
      <div className="psm-card-head">
        <div>
          <div className="psm-eyebrow">Overview Stats</div>
          <h2 className="psm-card-title">Reference</h2>
        </div>
      </div>
      <div className="psm-stat-list">
        <StatRow label="Market Cap" value={fmtLarge(overview.stats.market_cap)} missing={overview.stats.market_cap == null} />
        <StatRow label="P/E TTM" value={fmtNumber(overview.stats.trailing_pe)} missing={overview.stats.trailing_pe == null} />
        <StatRow label="EPS TTM" value={fmtCurrency(overview.stats.trailing_eps)} missing={overview.stats.trailing_eps == null} />
        <StatRow label="Volume" value={fmtNumber(overview.stats.volume, 0)} missing={overview.stats.volume == null} />
        <StatRow label="Avg Volume" value={fmtNumber(overview.stats.average_volume, 0)} missing={overview.stats.average_volume == null} />
        <StatRow label="Beta" value={fmtNumber(overview.stats.beta)} missing={overview.stats.beta == null} />
      </div>
    </section>
  );
}

function DetailItem({ label, value, missing = false }: { label: string; value: string; missing?: boolean }) {
  return (
    <article className="psm-detail-item">
      <span className="psm-stat-label">{label}</span>
      <span className={`psm-detail-value${missing ? " missing" : ""}`}>{missing ? "Unavailable" : value}</span>
    </article>
  );
}

function StatRow({ label, value, missing = false }: { label: string; value: string; missing?: boolean }) {
  return (
    <div className="psm-stat-row">
      <span className="psm-stat-label">{label}</span>
      <span className={`psm-stat-value${missing ? " missing" : ""}`}>{missing ? "Unavailable" : value}</span>
    </div>
  );
}

function LoadingShell() {
  return (
    <AppShell
      sidebar={<aside className="psm-side"><div className="psm-brand"><Image className="psm-brand-mark" src="/design-system/logo-monogram.svg" alt="" width={34} height={34} /><div className="psm-brand-copy"><div className="psm-brand-name">Prism</div><div className="psm-brand-sub">Loading</div></div></div></aside>}
      topbar={<header className="psm-top"><div className="psm-search-form"><span className="psm-icon icon-search" aria-hidden /><span className="psm-muted-copy">Loading Prism…</span></div></header>}
    >
      <div className="psm-loading-shell">
        <section className="psm-card psm-skeleton" />
        <section className="psm-card psm-skeleton" />
      </div>
    </AppShell>
  );
}
