import type { MetricsTimeBucket, MetricsView } from "@batch-cooking/shared";
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import {
  CartesianGrid,
  Line,
  LineChart,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
} from "recharts";
import { adminApiClient } from "../../api/client";
import "../admin-page.scss";
import "./dashboard-page.scss";
import { formatCount, kpiTiles, seriesTotal, shortDay } from "./dashboard";

/** Load state for `GET /admin/metrics` — same discriminated-union shape as apps/web's page states. */
type DashboardState =
  | { status: "loading" }
  | { status: "loaded"; metrics: MetricsView }
  | { status: "error" };

const RANGE_DAYS = 30;

/**
 * Usage-metrics dashboard. KPI tiles from the snapshot, then a small line
 * chart per instrumented time series over the last {@link RANGE_DAYS} days.
 * Fed by `GET /admin/metrics`; read-only, refetched only on mount.
 */
export function DashboardPage() {
  const { t } = useTranslation();
  const [state, setState] = useState<DashboardState>({ status: "loading" });

  useEffect(() => {
    let cancelled = false;
    setState({ status: "loading" });
    adminApiClient
      .getMetrics(RANGE_DAYS)
      .then((metrics) => {
        if (!cancelled) setState({ status: "loaded", metrics });
      })
      .catch(() => {
        if (!cancelled) setState({ status: "error" });
      });
    return () => {
      cancelled = true;
    };
  }, []);

  return (
    <div className="admin-page">
      <h1 className="admin-page__title">{t("admin.dashboard.title")}</h1>
      <p className="admin-page__lead">{t("admin.dashboard.lead")}</p>

      {state.status === "loading" && (
        <p className="admin-page__placeholder">{t("admin.common.loading")}</p>
      )}
      {state.status === "error" && (
        <p className="admin-page__placeholder">{t("admin.common.loadError")}</p>
      )}
      {state.status === "loaded" && <DashboardBody metrics={state.metrics} />}
    </div>
  );
}

function DashboardBody({ metrics }: { metrics: MetricsView }) {
  const { t } = useTranslation();
  const { snapshot, series } = metrics;

  const charts: { key: string; buckets: MetricsTimeBucket[] }[] = [
    { key: "signups", buckets: series.signups },
    { key: "recipesCreated", buckets: series.recipesCreated },
    { key: "planningItemsAdded", buckets: series.planningItemsAdded },
    { key: "correctionsSubmitted", buckets: series.correctionsSubmitted },
    { key: "trainingSuggestions", buckets: series.trainingSuggestions },
  ];

  return (
    <>
      <section className="kpi-grid">
        {kpiTiles(snapshot).map((tile) => (
          <div className="kpi-tile" key={tile.labelKey}>
            <span className="kpi-tile__value">{formatCount(tile.value)}</span>
            <span className="kpi-tile__label">{t(`admin.dashboard.kpi.${tile.labelKey}`)}</span>
          </div>
        ))}
      </section>

      <section className="chart-grid">
        {charts.map(({ key, buckets }) => (
          <article className="chart-card" key={key}>
            <header className="chart-card__head">
              <h2>{t(`admin.dashboard.series.${key}`)}</h2>
              <span className="chart-card__total">
                {t("admin.dashboard.windowTotal", { n: seriesTotal(buckets) })}
              </span>
            </header>
            <TrendChart buckets={buckets} />
          </article>
        ))}
      </section>

      <section className="breakdown">
        <h2>{t("admin.dashboard.recipesBySource")}</h2>
        {snapshot.recipesBySource.length === 0 ? (
          <p className="admin-page__placeholder">{t("admin.dashboard.noImports")}</p>
        ) : (
          <ul className="breakdown__list">
            {snapshot.recipesBySource.map((row) => (
              <li key={row.key}>
                <span>{row.label}</span>
                <span>{formatCount(row.count)}</span>
              </li>
            ))}
          </ul>
        )}
      </section>

      {metrics.events.length > 0 && (
        <section className="breakdown">
          <h2>{t("admin.dashboard.events")}</h2>
          <ul className="breakdown__list">
            {metrics.events.map((event) => (
              <li key={event.type}>
                <span>{event.type}</span>
                <span>{formatCount(seriesTotal(event.buckets))}</span>
              </li>
            ))}
          </ul>
        </section>
      )}
    </>
  );
}

/** A compact 30-day line chart for one metrics series. */
function TrendChart({ buckets }: { buckets: MetricsTimeBucket[] }) {
  const data = buckets.map((bucket) => ({ day: shortDay(bucket.date), count: bucket.count }));
  return (
    <div className="chart-card__body">
      <ResponsiveContainer width="100%" height={160}>
        <LineChart data={data} margin={{ top: 4, right: 8, bottom: 0, left: -20 }}>
          <CartesianGrid strokeDasharray="3 3" stroke="var(--color-border)" />
          <XAxis
            dataKey="day"
            tick={{ fontSize: 10, fill: "var(--color-text-muted)" }}
            interval="preserveStartEnd"
            minTickGap={24}
          />
          <YAxis
            allowDecimals={false}
            width={40}
            tick={{ fontSize: 10, fill: "var(--color-text-muted)" }}
          />
          <Tooltip
            contentStyle={{
              background: "var(--color-surface)",
              border: "1px solid var(--color-border)",
              borderRadius: 8,
              fontSize: 12,
            }}
          />
          <Line
            type="monotone"
            dataKey="count"
            stroke="var(--color-primary)"
            strokeWidth={2}
            dot={false}
          />
        </LineChart>
      </ResponsiveContainer>
    </div>
  );
}
