/**
 * =============================================================================
 * QWHPI — Quebec Weekly Housing Price Index
 * Author  : Simon-Pierre Boucher
 * Contact : contact@spboucher.ai
 * File    : web/components/DataTable.tsx
 * Purpose : Sortable, filterable observations table under each chart —
 *           uncertainty (CI, grade) always shown.
 * =============================================================================
 */
"use client";

import { useMemo, useState } from "react";
import type { Observation } from "../lib/api";

type SortKey = "period" | "index_smoothed" | "monthly_pct" | "yoy_pct"
  | "transactions";

const COLS: { key: SortKey | string; label: string; sortable: boolean }[] = [
  { key: "period", label: "Period", sortable: true },
  { key: "index_smoothed", label: "Index", sortable: true },
  { key: "ci", label: "95% CI", sortable: false },
  { key: "monthly_pct", label: "MoM", sortable: true },
  { key: "yoy_pct", label: "YoY", sortable: true },
  { key: "representative_value", label: "$ value", sortable: false },
  { key: "transactions", label: "Sales", sortable: true },
  { key: "reliability_grade", label: "Grade", sortable: false },
];

function pct(v: number | null): string {
  return v == null ? "—" : `${v > 0 ? "+" : ""}${v.toFixed(2)}%`;
}

export default function DataTable({ observations }: { observations: Observation[] }) {
  const [sortKey, setSortKey] = useState<SortKey>("period");
  const [desc, setDesc] = useState(true);
  const [filter, setFilter] = useState("");

  const rows = useMemo(() => {
    let r = observations;
    if (filter) r = r.filter((o) => o.period.includes(filter));
    return [...r].sort((a, b) => {
      const av = a[sortKey] ?? -Infinity;
      const bv = b[sortKey] ?? -Infinity;
      const cmp = typeof av === "string"
        ? String(av).localeCompare(String(bv))
        : Number(av) - Number(bv);
      return desc ? -cmp : cmp;
    });
  }, [observations, sortKey, desc, filter]);

  const onSort = (key: string, sortable: boolean) => {
    if (!sortable) return;
    if (sortKey === key) setDesc(!desc);
    else {
      setSortKey(key as SortKey);
      setDesc(true);
    }
  };

  return (
    <div>
      <div className="controls" style={{ margin: "10px 0" }}>
        <input
          type="text"
          placeholder="Filter period… (e.g. 2024)"
          value={filter}
          aria-label="Filter table by period"
          onChange={(e) => setFilter(e.target.value)}
          style={{
            background: "var(--surface-1)", color: "var(--text-primary)",
            border: "1px solid var(--border-strong)", borderRadius: 10,
            padding: "7px 12px", fontSize: 13.5, fontFamily: "inherit",
          }}
        />
        <span className="note">{rows.length} rows</span>
      </div>
      <div style={{ overflowX: "auto", maxHeight: 420, overflowY: "auto" }}>
        <table className="data" style={{ fontSize: 13 }}>
          <thead>
            <tr>
              {COLS.map((c) => (
                <th key={c.key}
                    onClick={() => onSort(c.key, c.sortable)}
                    style={{ cursor: c.sortable ? "pointer" : "default",
                             userSelect: "none" }}
                    aria-sort={sortKey === c.key
                      ? (desc ? "descending" : "ascending") : "none"}>
                  {c.label}
                  {c.sortable && sortKey === c.key && (desc ? " ↓" : " ↑")}
                </th>
              ))}
            </tr>
          </thead>
          <tbody>
            {rows.map((o) => (
              <tr key={o.period}>
                <td>{o.period}{o.is_partial_month ? " *" : ""}</td>
                <td>{o.index_smoothed.toFixed(2)}</td>
                <td className="note">
                  {o.lower_95.toFixed(1)}–{o.upper_95.toFixed(1)}
                </td>
                <td className={o.monthly_pct != null && o.monthly_pct < 0
                  ? "delta down" : "delta up"}>{pct(o.monthly_pct)}</td>
                <td className={o.yoy_pct != null && o.yoy_pct < 0
                  ? "delta down" : "delta up"}>{pct(o.yoy_pct)}</td>
                <td>{o.representative_value
                  ? `$${Math.round(o.representative_value).toLocaleString("en-CA")}` : "—"}</td>
                <td>{o.transactions}</td>
                <td>{o.reliability_grade}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      <p className="note" style={{ marginTop: 8 }}>* partial month (nowcast)</p>
    </div>
  );
}
