/**
 * =============================================================================
 * QWHPI — Quebec Weekly Housing Price Index
 * Author  : Simon-Pierre Boucher
 * Contact : contact@spboucher.ai
 * File    : web/app/page.tsx
 * Purpose : Overview — ticker tape, animated mega hero on a draw-in chart,
 *           regional podium, metric tiles, pulse heatmap table.
 * =============================================================================
 */
"use client";

import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import {
  fetchOverview,
  fetchSeries,
  fetchStats,
  marketReportUrl,
  type Observation,
  type OverviewRow,
  type SeriesStats,
} from "../lib/api";
import CountUp from "../components/CountUp";
import HeroChart from "../components/HeroChart";
import ReliabilityBadge from "../components/ReliabilityBadge";
import { DashboardSkeleton } from "../components/Skeleton";
import Sparkline from "../components/Sparkline";
import Ticker from "../components/Ticker";

function Delta({ v, suffix = "%" }: { v: number | null; suffix?: string }) {
  if (v == null) return <span className="delta">—</span>;
  const cls = v >= 0 ? "delta up" : "delta down";
  return (
    <span className={cls}>
      {v >= 0 ? "▲" : "▼"} {Math.abs(v).toFixed(2)}
      {suffix}
    </span>
  );
}

function heatStyle(v: number | null, lo: number, hi: number) {
  if (v == null) return {};
  if (v < 0) return { background: "rgba(227, 73, 72, 0.18)" };
  const ramp = ["#cde2fb", "#9ec5f4", "#6da7ec", "#3987e5", "#256abf"];
  const t = hi === lo ? 0.5 : Math.max(0, Math.min(0.999, (v - lo) / (hi - lo)));
  const c = ramp[Math.floor(t * ramp.length)];
  return {
    background: c,
    color: c === "#256abf" || c === "#3987e5" ? "#fff" : "#0b0b0b",
  };
}

const TYPES = ["all", "unifamilial", "condo", "plex"];
const MEDALS = ["🥇", "🥈", "🥉"];

export default function Overview() {
  const router = useRouter();
  const [stats, setStats] = useState<SeriesStats | null>(null);
  const [rows, setRows] = useState<OverviewRow[]>([]);
  const [series, setSeries] = useState<Observation[]>([]);
  const [ptype, setPtype] = useState("all");
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    Promise.all([
      fetchStats("quebec", ptype),
      fetchOverview("region", ptype),
      fetchSeries("quebec", ptype),
    ])
      .then(([s, o, se]) => {
        setStats(s);
        setRows(o.rows);
        setSeries(se.observations);
        setError(null);
      })
      .catch((e) => setError(String(e)));
  }, [ptype]);

  if (error)
    return (
      <div className="card" style={{ marginTop: 32 }}>
        <strong>API unreachable.</strong>
        <p className="note">Start it with <code>make api</code> — {error}</p>
      </div>
    );
  if (!stats) return <DashboardSkeleton />;

  const yoys = rows.map((r) => r.yoy_pct).filter((v): v is number => v != null);
  const lo = Math.min(...yoys, 0);
  const hi = Math.max(...yoys, 1);
  const podium = rows.slice(0, 3);

  return (
    <>
      <Ticker ptype={ptype} />

      <div className="hero">
        <div>
          <div className="hero-kicker">Month of {stats.period}</div>
          <h1>Quebec housing prices,<br />measured monthly, robustly.</h1>
          <p className="lede">
            Robust hedonic index (rolling-time-dummy) · base 2021 = 100 ·
            uncertainty always displayed
          </p>
          <div className="controls" style={{ margin: "16px 0 0" }}>
            <div className="seg" role="group" aria-label="Property type">
              {TYPES.map((t) => (
                <button key={t} aria-pressed={ptype === t}
                        onClick={() => setPtype(t)}>
                  {t}
                </button>
              ))}
            </div>
            <a className="primary" href={marketReportUrl(ptype)} target="_blank"
               rel="noreferrer">
              ⤓ Market report (PDF)
            </a>
          </div>
        </div>
        <div className="hero-mega">
          <span className="big">
            <CountUp value={stats.index} decimals={1} />
          </span>
          <span className="sub">
            QHPI-QC · 95% CI {stats.lower_95.toFixed(1)}–{stats.upper_95.toFixed(1)}
            {stats.at_record_high && (
              <span className="record-chip"> · ★ record high</span>
            )}
          </span>
          <span className="sub">
            <Delta v={stats.yoy_pct} /> YoY · <Delta v={stats.since_2021_pct} /> since 2021
          </span>
        </div>
      </div>

      <HeroChart observations={series} />

      <h2>Fastest-appreciating regions</h2>
      <div className="podium fade-up">
        {podium.map((r, i) => (
          <div key={r.geography_id}
               className={`card hoverable p${i + 1}`}
               style={{ cursor: "pointer" }}
               onClick={() =>
                 router.push(`/explore?geography=${r.geography_id}&type=${ptype}`)}>
            <div style={{ display: "flex", justifyContent: "space-between",
                          alignItems: "baseline" }}>
              <strong>{MEDALS[i]} {r.geography_name}</strong>
              <ReliabilityBadge grade={r.reliability_grade} />
            </div>
            <div style={{ display: "flex", justifyContent: "space-between",
                          alignItems: "flex-end", marginTop: 8 }}>
              <div>
                <div className="stat-tile">
                  <span className="value" style={{ fontSize: 26 }}>
                    <Delta v={r.yoy_pct} />
                  </span>
                  <span className="note">
                    index {r.index.toFixed(1)}
                    {r.at_record_high ? " · at peak" : ""}
                  </span>
                </div>
              </div>
              <Sparkline values={r.spark} width={110} height={34} />
            </div>
          </div>
        ))}
      </div>

      <div className="grid cols-8 fade-up d1" style={{ marginTop: 24 }}>
        {[
          ["Dollar value", stats.representative_value
            ? <CountUp key="v" value={stats.representative_value} decimals={0} prefix="$" />
            : <span key="v">—</span>],
          ["1 month", <Delta key="a" v={stats.monthly_pct} />],
          ["3 months", <Delta key="b" v={stats.three_month_pct} />],
          ["6 months", <Delta key="c" v={stats.six_month_pct} />],
          ["CAGR", <Delta key="d" v={stats.cagr_pct} />],
          ["Volatility 12m", <span key="f">{stats.volatility_12m_pct.toFixed(2)}%</span>],
          ["Sales 12m", <CountUp key="g" value={stats.volume_12m} decimals={0} />],
          ["$ volume 12m", <span key="h">${(stats.dollar_volume_12m / 1e9).toFixed(1)}B</span>],
        ].map(([label, val]) => (
          <div className="card hoverable stat-tile mini-tile" key={String(label)}>
            <span className="label">{label}</span>
            <span className="value">{val}</span>
          </div>
        ))}
      </div>

      <h2>Regional pulse — {ptype} · month of {stats.period}</h2>
      <div className="card fade-up d2" style={{ padding: "8px 12px", overflowX: "auto" }}>
        <table className="pulse">
          <thead>
            <tr>
              <th>Region</th><th>Trend</th><th>Index</th><th>1m</th><th>3m</th>
              <th>6m</th><th>YoY</th><th>Since 2021</th><th>Vs peak</th>
              <th>Sales 12m</th><th>$ value</th><th>Grade</th>
            </tr>
          </thead>
          <tbody>
            {rows.map((r) => (
              <tr key={r.geography_id}
                  onClick={() =>
                    router.push(`/explore?geography=${r.geography_id}&type=${ptype}`)}>
                <td>
                  {r.geography_name}
                  {r.at_record_high && <span className="record-chip"> ★</span>}
                </td>
                <td><Sparkline values={r.spark} width={84} height={22} /></td>
                <td>{r.index.toFixed(1)}</td>
                <td><Delta v={r.monthly_pct} /></td>
                <td><Delta v={r.three_month_pct} /></td>
                <td><Delta v={r.six_month_pct} /></td>
                <td className="heat" style={heatStyle(r.yoy_pct, lo, hi)}>
                  {r.yoy_pct == null ? "—" : `${r.yoy_pct > 0 ? "+" : ""}${r.yoy_pct.toFixed(2)}%`}
                </td>
                <td><Delta v={r.since_2021_pct} /></td>
                <td>{r.drawdown_pct === 0 ? "peak" : `${r.drawdown_pct.toFixed(1)}%`}</td>
                <td>{r.volume_12m.toLocaleString()}</td>
                <td>{r.representative_value
                  ? `$${Math.round(r.representative_value / 1000)}k` : "—"}</td>
                <td>{r.reliability_grade}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      <p className="note" style={{ marginTop: 12 }}>
        ★ = record high · YoY column shaded by appreciation · click a row to
        explore the series · press <kbd style={{
          background: "var(--surface-2)", border: "1px solid var(--border)",
          borderRadius: 5, padding: "0 5px", fontSize: 11,
        }}>⌘K</kbd> to jump anywhere.
      </p>
    </>
  );
}
