/**
 * earth-now.co
 * Author:  Simon-Pierre Boucher
 * Contact: contact@spboucher.ai
 * File:    apps/web/components/MetricDetail.tsx
 * Purpose: Per-metric page body — big live counter and the metric's own methodology section (model family, sources, uncertainty)
 */

"use client";

import Link from "next/link";
import { useEffect, useMemo, useState } from "react";
import { formatUncertainty, formatValue, type CounterModel } from "@earth-now/counter";
import type { Locale, MetricSummary } from "@/lib/api";
import { hintsFor, resolvePrimaryWindow } from "@/lib/derived";
import { I18nProvider, useI18n } from "@/lib/i18n";
import { formatDateUtc, isLocale, type MessageKey } from "@/lib/messages";
import { tierFor } from "@/lib/tiers";
import LiveCounter from "./LiveCounter";

const LOCALE_STORAGE_KEY = "earth-now.locale";
const PERCENT_HINTS = { decimals: 0, unit: "%" } as const;

export interface MetricDetailProps {
  metric: MetricSummary;
  model: CounterModel | null;
}

export default function MetricDetail({ metric, model }: MetricDetailProps) {
  const [locale, setLocaleState] = useState<Locale>("fr");
  useEffect(() => {
    const saved = window.localStorage.getItem(LOCALE_STORAGE_KEY);
    if (isLocale(saved)) setLocaleState(saved);
  }, []);
  useEffect(() => {
    document.documentElement.lang = locale;
  }, [locale]);
  const setLocale = (next: Locale) => {
    setLocaleState(next);
    window.localStorage.setItem(LOCALE_STORAGE_KEY, next);
  };
  return (
    <I18nProvider locale={locale} setLocale={setLocale}>
      <MetricDetailBody metric={metric} model={model} />
    </I18nProvider>
  );
}

function MetricDetailBody({ metric, model }: MetricDetailProps) {
  const { locale, t } = useI18n();
  const sessionStart = useMemo(() => Date.now(), []);
  const live = model !== null && tierFor(metric, model, sessionStart) === "live";
  const hints = hintsFor(metric, locale);

  return (
    <div className="mx-auto max-w-4xl px-4 pb-16">
      <nav className="py-6 text-sm">
        <Link href="/" className="text-accent hover:opacity-80">
          {t("metric.back")}
        </Link>
      </nav>

      <LiveCounter
        metric={metric}
        model={model ?? undefined}
        window={resolvePrimaryWindow(metric)}
        sessionStart={sessionStart}
        size="display"
        live={live}
        noLink
      />

      <section aria-labelledby="metric-method" className="mt-10">
        <h2 id="metric-method" className="text-lg font-semibold text-ink">
          {t("metric.methodTitle")}
        </h2>
        <p className="mt-2 max-w-3xl text-sm leading-relaxed text-ink2">
          {familyExplanation(metric.model, t)}
        </p>

        <dl className="mt-5 grid grid-cols-1 gap-x-8 gap-y-3 text-sm sm:grid-cols-2">
          <MethodRow label={t("methodology.kind")}>
            {t(`kind.${metric.kind}` as MessageKey)} · {t(`domain.${metric.domain}` as MessageKey)}
          </MethodRow>
          <MethodRow label={t("methodology.model")}>
            {metric.model}
            {model !== null && model.modelVersion !== metric.model
              ? ` (${model.modelVersion})`
              : ""}{" "}
            — {t("metric.level")} {String(metric.level)}
          </MethodRow>
          {model !== null && (
            <MethodRow label={t("methodology.observed")}>
              {formatDateUtc(model.observedAt, locale)}
            </MethodRow>
          )}
          {model?.uncertainty !== undefined && (
            <MethodRow label={t("methodology.uncertainty")}>
              {formatUncertainty(model.uncertainty.low, model.uncertainty.high, hints, {
                locale,
              })}{" "}
              {metric.display.unit[locale]}
            </MethodRow>
          )}
          {metric.uncertaintyFraction !== undefined && (
            <MethodRow label={t("methodology.uncertainty")}>
              ± {formatValue(metric.uncertaintyFraction * 100, PERCENT_HINTS, { locale })} % (
              {t("info.estimateNote")})
            </MethodRow>
          )}
          <MethodRow label={t("metric.windows")}>
            {metric.windows.map((w) => t(`window.${w}` as MessageKey)).join(" · ")}
          </MethodRow>
        </dl>

        <h3 className="mt-6 text-sm font-semibold uppercase tracking-wide text-ink2">
          {t("methodology.source")}
        </h3>
        <ul className="mt-2 space-y-2 text-sm">
          {metric.sources.map((source) => (
            <li key={source.id} className="rounded-xl border bg-surface px-4 py-3">
              <a
                href={source.url}
                target="_blank"
                rel="noreferrer"
                className="font-medium text-accent underline decoration-accent/40 hover:opacity-80"
              >
                {source.name}
              </a>
              <div className="mt-1 text-xs text-ink2">
                {t("methodology.license")} : {source.license} · {t("methodology.cadence")} :{" "}
                {source.cadence}
              </div>
            </li>
          ))}
        </ul>

        {metric.editorialNote !== undefined && (
          <p className="mt-4 max-w-3xl rounded-xl bg-wash px-4 py-3 text-sm text-ink2">
            {metric.editorialNote[locale]}
          </p>
        )}

        <p className="mt-6 text-sm">
          <Link href="/methodology" className="text-accent underline decoration-accent/40 hover:opacity-80">
            {t("metric.fullMethodology")}
          </Link>
        </p>
      </section>
    </div>
  );
}

function MethodRow({ label, children }: { label: string; children: React.ReactNode }) {
  return (
    <div>
      <dt className="text-xs uppercase tracking-wide text-muted">{label}</dt>
      <dd className="mt-0.5 text-ink">{children}</dd>
    </div>
  );
}

/** One-sentence how-it-works per model family (the per-metric methodology promise). */
function familyExplanation(family: string, t: (key: MessageKey) => string): string {
  const known = new Set([
    "seasonal-spline-v2",
    "keeling-fusion-v1",
    "seasonal-ytd-v1",
    "linear-ytd-v1",
    "linear-stock-v1",
    "static-rt-v1",
    "derived",
  ]);
  return known.has(family) ? t(`explain.${family}` as MessageKey) : t("explain.default");
}
