"use client";

import { useState } from "react";
import { useQuery } from "@tanstack/react-query";
import {
  Coins,
  Gauge,
  Layers,
  MousePointerClick,
  Repeat,
  Route,
  Target,
  TriangleAlert,
} from "lucide-react";
import { Alert } from "@/components/ui/alert";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { StatCard } from "@/components/shared/stat-card";
import { useI18n, useT } from "@/i18n";
import type { Dictionary } from "@/i18n/dictionaries/en";
import { formatNumber } from "@/lib/format";
import { friendlyErrorMessage } from "@/lib/errors";
import { queryKeys } from "@/lib/query-keys";
import {
  defaultKpiRange,
  getDispatchKpis,
  kpiDaysAgo,
  kpiPercent,
  kpiToday,
  KPI_MAX_DAYS,
  type DispatchKpiRange,
} from "@/services/dispatch";

/**
 * The counters, in the order they tell the story: a list is shown, a captain is chosen, the
 * assignment is made or refused, and the routing behind it is paid for.
 *
 * Named explicitly rather than iterated over the response, because the row order *is* the
 * explanation — and because an unlabelled metric key on an operations screen is worse than not
 * showing it at all.
 */
const COUNTER_ROWS: ReadonlyArray<{ key: string; label: keyof Dictionary }> = [
  {
    key: "suggestion.generated",
    label: "performance.counter.suggestionGenerated",
  },
  { key: "suggestion.chosen", label: "performance.counter.suggestionChosen" },
  {
    key: "suggestion.chosen_first",
    label: "performance.counter.suggestionChosenFirst",
  },
  { key: "assignment.made", label: "performance.counter.assignmentMade" },
  { key: "assignment.batched", label: "performance.counter.assignmentBatched" },
  { key: "assignment.failed", label: "performance.counter.assignmentFailed" },
  { key: "routing.answered", label: "performance.counter.routingAnswered" },
  { key: "routing.fallback", label: "performance.counter.routingFallback" },
  { key: "routing.elements", label: "performance.counter.routingElements" },
  {
    key: "routeplan.recomputed",
    label: "performance.counter.routeplanRecomputed",
  },
  { key: "delivery.completed", label: "performance.counter.deliveryCompleted" },
];

/**
 * How the dispatch algorithm is doing over a window.
 *
 * **A missing number is not a zero.** Every rate here comes back `null` when the window held no
 * denominator — a quiet day has no batch rate — and the tiles draw that as a dash, with the
 * meaning spelled out below the grid. Showing `0%` instead would say the fleet never batches,
 * which is a different statement, and a false one.
 */
export function DispatchKpis() {
  const t = useT();
  const { locale } = useI18n();
  // Held in component state rather than the URL: the two dates are only meaningful together, and
  // a half-typed range in the address bar is a shareable link that answers 422.
  const [range, setRange] = useState<DispatchKpiRange>(defaultKpiRange);

  const invalid = range.from > range.to;

  const query = useQuery({
    queryKey: queryKeys.dispatch.kpis(range),
    queryFn: async () => (await getDispatchKpis(range)).Model ?? null,
    // The server refuses a backwards range; no point spending the round trip to be told.
    enabled: !invalid,
  });

  const kpis = query.data;
  const dash = "—";
  const ms = (value: number | null | undefined) =>
    value === null || value === undefined
      ? dash
      : t("performance.ms", { value: formatNumber(value, locale) });
  const percent = (rate: number | null | undefined) => {
    const value = kpiPercent(rate);
    return value === null ? dash : `${formatNumber(value, locale)}%`;
  };
  const ratio = (value: number | null | undefined) =>
    value === null || value === undefined ? dash : formatNumber(value, locale);

  const preset = (from: string) => () => setRange({ from, to: kpiToday() });

  return (
    <div className="space-y-6">
      <Card>
        <CardContent className="flex flex-wrap items-end gap-4 pt-6">
          <div className="space-y-1.5">
            <Label htmlFor="kpi-from">{t("performance.from")}</Label>
            <Input
              id="kpi-from"
              type="date"
              value={range.from}
              min={kpiDaysAgo(KPI_MAX_DAYS)}
              max={kpiToday()}
              onChange={(event) =>
                setRange((current) => ({
                  ...current,
                  from: event.target.value,
                }))
              }
            />
          </div>
          <div className="space-y-1.5">
            <Label htmlFor="kpi-to">{t("performance.to")}</Label>
            <Input
              id="kpi-to"
              type="date"
              value={range.to}
              min={range.from}
              max={kpiToday()}
              onChange={(event) =>
                setRange((current) => ({ ...current, to: event.target.value }))
              }
            />
          </div>
          <div className="flex flex-wrap items-center gap-2">
            <Button
              type="button"
              variant="outline"
              size="sm"
              onClick={preset(kpiToday())}
            >
              {t("performance.presetToday")}
            </Button>
            <Button
              type="button"
              variant="outline"
              size="sm"
              onClick={preset(kpiDaysAgo(6))}
            >
              {t("performance.presetWeek")}
            </Button>
            <Button
              type="button"
              variant="outline"
              size="sm"
              onClick={preset(kpiDaysAgo(29))}
            >
              {t("performance.presetMonth")}
            </Button>
          </div>
          <p className="basis-full text-xs text-muted-foreground">
            {t("performance.rangeHint", { days: String(KPI_MAX_DAYS) })}
          </p>
        </CardContent>
      </Card>

      {invalid ? (
        <Alert variant="warning" title={t("performance.rangeInvalid")} />
      ) : query.isError ? (
        <Alert variant="destructive" title={t("performance.loadFailed")}>
          {friendlyErrorMessage(query.error, t)}
        </Alert>
      ) : null}

      <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
        <StatCard
          label={t("performance.suggestionLatency")}
          value={ms(kpis?.suggestion_to_display.p95_ms)}
          icon={Gauge}
          tone="primary"
          hint={t("performance.suggestionLatencyHint", {
            p50: ms(kpis?.suggestion_to_display.p50_ms),
          })}
          loading={query.isPending}
        />
        <StatCard
          label={t("performance.decisionLatency")}
          value={ms(kpis?.display_to_assign.p95_ms)}
          icon={MousePointerClick}
          tone="accent"
          hint={t("performance.decisionLatencyHint", {
            p50: ms(kpis?.display_to_assign.p50_ms),
          })}
          loading={query.isPending}
        />
        <StatCard
          label={t("performance.firstChoice")}
          value={percent(kpis?.first_suggestion_acceptance_rate)}
          icon={Target}
          tone="success"
          hint={t("performance.firstChoiceHint")}
          loading={query.isPending}
        />
        <StatCard
          label={t("performance.batchRate")}
          value={percent(kpis?.batch_rate)}
          icon={Layers}
          tone="primary"
          hint={t("performance.batchRateHint")}
          loading={query.isPending}
        />
        <StatCard
          label={t("performance.failureRate")}
          value={percent(kpis?.assignment_failure_rate)}
          icon={TriangleAlert}
          tone="warning"
          hint={t("performance.failureRateHint")}
          loading={query.isPending}
        />
        <StatCard
          label={t("performance.fallbackRate")}
          value={percent(kpis?.routing_fallback_rate)}
          icon={Route}
          tone="warning"
          hint={t("performance.fallbackRateHint")}
          loading={query.isPending}
        />
        <StatCard
          label={t("performance.mapsCost")}
          value={ratio(kpis?.maps_cost_per_delivery)}
          icon={Coins}
          tone="accent"
          hint={t("performance.mapsCostHint", {
            elements: ratio(kpis?.routing_elements_per_assignment),
          })}
          loading={query.isPending}
        />
        <StatCard
          label={t("performance.recomputes")}
          value={ratio(kpis?.recomputes_per_delivery)}
          icon={Repeat}
          tone="muted"
          hint={t("performance.recomputesHint")}
          loading={query.isPending}
        />
      </div>

      <p className="text-xs text-muted-foreground">
        {t("performance.dashMeaning")}
      </p>

      <Card>
        <CardHeader>
          <CardTitle>{t("performance.countersTitle")}</CardTitle>
        </CardHeader>
        <CardContent>
          <p className="mb-4 text-sm text-muted-foreground">
            {t("performance.countersHint")}
          </p>
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>{t("performance.counter")}</TableHead>
                <TableHead>{t("performance.count")}</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {COUNTER_ROWS.map((row) => (
                <TableRow key={row.key}>
                  <TableCell>
                    <p className="font-medium text-foreground">
                      {t(row.label)}
                    </p>
                    <p className="text-xs text-muted-foreground" dir="ltr">
                      {row.key}
                    </p>
                  </TableCell>
                  <TableCell className="numeric">
                    {kpis
                      ? formatNumber(kpis.totals[row.key] ?? 0, locale)
                      : dash}
                  </TableCell>
                </TableRow>
              ))}
            </TableBody>
          </Table>
        </CardContent>
      </Card>
    </div>
  );
}
