"use client";

import { useCallback, useEffect, useState } from "react";
import { get } from "@/lib/api";
import { InfoTip, Notice, PageHeader, Spinner } from "@/components/ui";
import { BarChart, DonutChart, LineChart } from "@/components/charts";
import { chf, num, pct, timeAgo } from "@/lib/format";
import { SCORE_TERM_BY_CODE } from "@/lib/glossary";

type Metrics = {
  generatedAt: string;
  queueDepth: number;
  productsLast24h: number;
  outcomes: { done: number; review: number; failed: number; other: number };
  failureRate: number;
  avgAqsPerAttribute: { attribute: string; avgAqs: number; samples: number }[];
  cost: {
    dailyTotalChf: number;
    perProductAvgChf: number;
    avgPerProductChf: number;
    lifetimeProducts: number;
    lifetimeTotalChf: number;
    perProductCeilingChf: number;
    dailyCeilingChf: number;
  };
  dailySeries: { day: string; cost_chf: number; products: number }[];
  killSwitch: { active: boolean; reason: string | null; tripped_at: string | null };
  recentRuns: {
    productId: string;
    outcome: string;
    aggregate: number;
    costChf: number;
    template: string;
    startedAt: string;
  }[];
};

type ErgoStats = {
  ok: boolean;
  transport: string;
  total: number;
  byStatus: Record<string, number>;
  error?: string;
};

export default function DashboardPage() {
  const [m, setM] = useState<Metrics | null>(null);
  const [ergo, setErgo] = useState<ErgoStats | null>(null);
  const [error, setError] = useState<string | null>(null);

  const load = useCallback(async () => {
    try {
      setM(await get<Metrics>("metrics"));
      setError(null);
    } catch (e) {
      setError((e as Error).message);
    }
    // Ergonode stats fetched separately so a connection error never blanks the dashboard.
    try {
      setErgo(await get<ErgoStats>("ergonode/stats"));
    } catch (e) {
      setErgo({ ok: false, transport: "?", total: 0, byStatus: {}, error: (e as Error).message });
    }
  }, []);

  useEffect(() => {
    load();
    const t = setInterval(load, 30_000); // dashboard data is well within the 5-min freshness target
    return () => clearInterval(t);
  }, [load]);

  if (error) return <Notice kind="error">Could not load metrics: {error}</Notice>;
  if (!m) return <Spinner label="Loading metrics…" />;

  const maxAqs = 1;

  return (
    <>
      <PageHeader title="Observability Dashboard" description="Pipeline health, throughput, quality and cost." />

      <p className="mb-4 text-xs text-slate-500" aria-live="polite">
        Data freshness: updated {timeAgo(m.generatedAt)} · auto-refreshes every 30s
      </p>

      <section aria-label="Key metrics" className="grid grid-cols-2 gap-4 lg:grid-cols-5">
        <Stat title="Queue depth" value={String(m.queueDepth)} hint="products in AI Research" />
        <Stat title="Processed (24h)" value={String(m.productsLast24h)} hint={`${m.outcomes.done} done · ${m.outcomes.review} review`} />
        <Stat title="Failure rate" value={pct(m.failureRate)} hint="review + failed / total" kind={m.failureRate > 0.3 ? "warn" : "ok"} />
        <Stat title="Cost today" value={chf(m.cost.dailyTotalChf)} hint={`ceiling ${chf(m.cost.dailyCeilingChf)}`} />
        <Stat
          title="Avg. cost / product"
          value={chf(m.cost.avgPerProductChf)}
          hint={`${num(m.cost.lifetimeProducts)} products · ${chf(m.cost.lifetimeTotalChf)} total`}
          kind={m.cost.avgPerProductChf > m.cost.perProductCeilingChf ? "warn" : "neutral"}
        />
      </section>

      <section className="card mt-6" aria-labelledby="ergo-h">
        <div className="mb-3 flex items-center justify-between">
          <h2 id="ergo-h" className="font-semibold text-slate-900">Ergonode</h2>
          {ergo && (
            <span className="text-xs text-slate-500">
              source: {ergo.transport}
              {ergo.ok ? ` · ${ergo.total} product(s) total` : ""}
            </span>
          )}
        </div>
        {!ergo ? (
          <p className="text-sm text-slate-500">Loading…</p>
        ) : ergo.ok ? (
          <div className="grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-5">
            {Object.entries(ergo.byStatus).map(([status, count]) => (
              <ErgoStat key={status} label={status} value={count} highlight={status === "New"} />
            ))}
          </div>
        ) : (
          <Notice kind="error">
            Could not read Ergonode: {ergo.error}. Check the connection in Admin Settings.
          </Notice>
        )}
        <p className="mt-3 text-xs text-slate-500">
          “New” products are picked up on the next polling cycle and worked through the workflow to “Done”, or flagged for review (Content Issue / Media Issue).
        </p>
      </section>

      <section className="mt-6 grid gap-6 lg:grid-cols-3">
        <div className="card">
          <h2 className="mb-3 font-semibold text-slate-900">Outcomes (24h)</h2>
          <DonutChart
            centerLabel="runs"
            segments={[
              { label: "Done", value: m.outcomes.done, color: "#16a34a" },
              { label: "Review", value: m.outcomes.review, color: "#d97706" },
              { label: "Failed", value: m.outcomes.failed, color: "#dc2626" },
              { label: "Other", value: m.outcomes.other, color: "#94a3b8" },
            ]}
          />
        </div>
        <div className="card">
          <h2 className="mb-1 font-semibold text-slate-900">Cost per day (7 days)</h2>
          <p className="mb-3 text-xs text-slate-500">
            Avg / product (24h): <strong>{chf(m.cost.perProductAvgChf)}</strong> · ceiling {chf(m.cost.perProductCeilingChf)}
          </p>
          <LineChart points={m.dailySeries.map((d) => ({ label: d.day.slice(5), value: d.cost_chf }))} formatValue={chf} />
        </div>
        <div className="card">
          <h2 className="mb-3 font-semibold text-slate-900">Products per day (7 days)</h2>
          <BarChart bars={m.dailySeries.map((d) => ({ label: d.day.slice(5), value: d.products }))} />
        </div>
      </section>

      <section className="card mt-6" aria-labelledby="aqs-h">
        <h2 id="aqs-h" className="mb-3 flex items-center gap-1.5 font-semibold text-slate-900">
          Average AQS per attribute (24h)
          <InfoTip label="About AQS">{SCORE_TERM_BY_CODE.AQS.desc}</InfoTip>
        </h2>
          {m.avgAqsPerAttribute.length === 0 ? (
            <p className="text-sm text-slate-500">No data yet.</p>
          ) : (
            <ul className="space-y-2">
              {m.avgAqsPerAttribute.map((a) => (
                <li key={a.attribute} className="text-sm">
                  <div className="flex justify-between">
                    <span className="font-medium text-slate-700">{a.attribute}</span>
                    <span className="tabular-nums text-slate-600">
                      {num(a.avgAqs)} <span className="text-slate-400">({a.samples})</span>
                    </span>
                  </div>
                  <div className="mt-1 h-2 rounded-sm bg-slate-100" role="presentation">
                    <div
                      className={`h-2 rounded-sm ${a.avgAqs >= 0.8 ? "bg-ok" : "bg-warn"}`}
                      style={{ width: `${(a.avgAqs / maxAqs) * 100}%` }}
                    />
                  </div>
                </li>
              ))}
            </ul>
          )}
        </section>

    </>
  );
}

function Stat({
  title,
  value,
  hint,
  kind = "neutral",
}: {
  title: string;
  value: string;
  hint?: string;
  kind?: "ok" | "warn" | "neutral";
}) {
  const color = kind === "ok" ? "text-ok" : kind === "warn" ? "text-warn" : "text-slate-900";
  return (
    <div className="card">
      <p className="text-sm text-slate-500">{title}</p>
      <p className={`mt-1 text-2xl font-semibold tabular-nums ${color}`}>{value}</p>
      {hint && <p className="mt-1 text-xs text-slate-500">{hint}</p>}
    </div>
  );
}

function ErgoStat({ label, value, highlight = false }: { label: string; value: number; highlight?: boolean }) {
  return (
    <div className={`rounded-md border p-3 ${highlight ? "border-brand bg-blue-50" : "border-slate-200"}`}>
      <p className="text-xs text-slate-500">{label}</p>
      <p className={`mt-1 text-2xl font-semibold tabular-nums ${highlight ? "text-brand-dark" : "text-slate-900"}`}>{value}</p>
    </div>
  );
}
