/**
 * =============================================================================
 * QWHPI — Quebec Weekly Housing Price Index
 * Author  : Simon-Pierre Boucher
 * Contact : contact@spboucher.ai
 * File    : web/app/api-docs/page.tsx
 * Purpose : API docs — copyable examples per endpoint + live playground.
 * =============================================================================
 */
"use client";

import { useState } from "react";
import { API_BASE } from "../../lib/api";

interface Endpoint {
  path: string;
  desc: string;
  example: string;
}

const ENDPOINTS: Endpoint[] = [
  { path: "/v1/index", desc: "Full monthly history for one series (CSV via &format=csv)",
    example: "/v1/index?geography=quebec-city&type=condo&from=2023-01&to=latest" },
  { path: "/v1/index/latest", desc: "Latest complete month for one series",
    example: "/v1/index/latest?geography=montreal&type=condo" },
  { path: "/v1/stats", desc: "Derived metrics: peak, drawdown, CAGR, volatility, momentum, ranks, volumes",
    example: "/v1/stats?geography=quebec&type=all" },
  { path: "/v1/stats/overview", desc: "One rich row per geography (heatmap data)",
    example: "/v1/stats/overview?level=region&type=all" },
  { path: "/v1/compare", desc: "Aligned multi-series comparison, optional rebasing",
    example: "/v1/compare?series=montreal:condo,quebec-city:condo&rebase_period=2022-01" },
  { path: "/v1/map", desc: "One metric per geography for a chosen month",
    example: "/v1/map?metric=yoy&level=region&period=2025-06" },
  { path: "/v1/report", desc: "Automatic PDF report (1-5 series, &format=json for data)",
    example: "/v1/report?series=montreal:condo&format=json" },
  { path: "/v1/vintages", desc: "First release vs current vintage (revision tracking)",
    example: "/v1/vintages?geography=quebec&type=all" },
  { path: "/v1/geographies", desc: "Published hierarchy + coverage matrix",
    example: "/v1/geographies" },
  { path: "/v1/meta", desc: "Model version, vintage, methodology summary",
    example: "/v1/meta" },
];

function CopyButton({ text }: { text: string }) {
  const [copied, setCopied] = useState(false);
  return (
    <button
      className="ctrl"
      style={{ padding: "4px 10px", fontSize: 12.5 }}
      aria-label="Copy request"
      onClick={() => {
        navigator.clipboard.writeText(text);
        setCopied(true);
        setTimeout(() => setCopied(false), 1500);
      }}
    >
      {copied ? "✓ Copied" : "Copy"}
    </button>
  );
}

export default function ApiDocs() {
  const [query, setQuery] = useState(ENDPOINTS[0].example);
  const [result, setResult] = useState<string>("");
  const [status, setStatus] = useState<string>("");
  const [running, setRunning] = useState(false);

  const run = async () => {
    setRunning(true);
    setStatus("");
    const t0 = performance.now();
    try {
      const res = await fetch(`${API_BASE}${query}`, {
        headers: { Accept: "application/json" },
      });
      const ms = Math.round(performance.now() - t0);
      const type = res.headers.get("content-type") ?? "";
      setStatus(`${res.status} ${res.statusText} · ${ms} ms · ${type.split(";")[0]}`);
      if (type.includes("json")) {
        const body = await res.json();
        setResult(JSON.stringify(body, null, 2).slice(0, 20000));
      } else {
        const body = await res.text();
        setResult(body.slice(0, 20000));
      }
    } catch (e) {
      setStatus("network error");
      setResult(String(e));
    }
    setRunning(false);
  };

  return (
    <>
      <h1>API</h1>
      <p className="lede">
        Every published series, statistic and report is available
        programmatically — confidence intervals and reliability grades on every
        observation, never hidden.{" "}
        <a href={`${API_BASE}/docs`} target="_blank" rel="noreferrer">
          Full OpenAPI reference ↗
        </a>
      </p>

      <h2>Playground</h2>
      <div className="card fade-up">
        <div className="controls" style={{ margin: 0 }}>
          <select
            aria-label="Endpoint template"
            value=""
            onChange={(e) => {
              if (e.target.value) setQuery(e.target.value);
            }}
          >
            <option value="">Insert an example…</option>
            {ENDPOINTS.map((ep) => (
              <option key={ep.path} value={ep.example}>{ep.path}</option>
            ))}
          </select>
          <input
            type="text"
            value={query}
            aria-label="Request path"
            onChange={(e) => setQuery(e.target.value)}
            onKeyDown={(e) => e.key === "Enter" && run()}
            style={{
              flex: "1 1 340px", background: "var(--surface-1)",
              color: "var(--text-primary)",
              border: "1px solid var(--border-strong)", borderRadius: 10,
              padding: "8px 12px", fontSize: 13.5,
              fontFamily: "ui-monospace, monospace",
            }}
          />
          <button className="primary" onClick={run} disabled={running}>
            {running ? "Running…" : "Run ▸"}
          </button>
        </div>
        {status && (
          <p className="note" style={{ margin: "10px 0 6px" }}>{status}</p>
        )}
        {result && (
          <pre style={{
            background: "var(--surface-2)", borderRadius: 10, padding: 14,
            fontSize: 12, maxHeight: 380, overflow: "auto", margin: "8px 0 0",
          }}>{result}</pre>
        )}
      </div>

      <h2>Endpoints</h2>
      <div className="grid" style={{ gap: 12 }}>
        {ENDPOINTS.map((ep) => {
          const curl = `curl "${API_BASE}${ep.example}"`;
          return (
            <div className="card hoverable" key={ep.path}
                 style={{ padding: "14px 18px" }}>
              <div style={{ display: "flex", justifyContent: "space-between",
                            alignItems: "baseline", gap: 10, flexWrap: "wrap" }}>
                <code style={{ fontSize: 14, fontWeight: 700 }}>{ep.path}</code>
                <span style={{ display: "flex", gap: 8 }}>
                  <button className="ctrl" style={{ padding: "4px 10px", fontSize: 12.5 }}
                          onClick={() => setQuery(ep.example)}>
                    Try ↑
                  </button>
                  <CopyButton text={curl} />
                </span>
              </div>
              <p className="note" style={{ margin: "6px 0" }}>{ep.desc}</p>
              <code style={{ fontSize: 12, color: "var(--text-secondary)",
                             display: "block", overflowX: "auto" }}>
                {curl}
              </code>
            </div>
          );
        })}
      </div>
    </>
  );
}
