import { createFileRoute } from "@tanstack/react-router";
import { useQuery } from "@tanstack/react-query";
import { useState } from "react";

import { api } from "@/lib/api";
import { formatEuros } from "@/lib/format";
import { cn } from "@/lib/utils";

import { Card } from "@/components/ui/Card";
import { Eyebrow } from "@/components/ui/Eyebrow";
import { GlossaryTerm } from "@/components/ui/GlossaryTerm";
import { GLOSSARY } from "@/lib/glossary";
import { EncaisseChart } from "@/components/charts/EncaisseChart";
import { DsoTrendChart } from "@/components/charts/DsoTrendChart";
import {
  PipelineChart,
  PipelineLegend,
} from "@/components/charts/PipelineChart";

type Range = 3 | 6 | 12;
type Granularity = "month" | "week";

type Timeseries = {
  range: Range;
  granularity: Granularity;
  paidByMonth: Array<{
    bucket: string;
    encaisseCents: number;
    paidCount: number;
    dsoDays: number;
  }>;
  pipelineByStatus: Array<{
    status: string;
    count: number;
    amountCents: number;
  }>;
};

export const Route = createFileRoute("/_app/insights")({
  component: InsightsPage,
});

const RANGES: { value: Range; label: string }[] = [
  { value: 3, label: "3 mois" },
  { value: 6, label: "6 mois" },
  { value: 12, label: "12 mois" },
];

function InsightsPage() {
  const [range, setRange] = useState<Range>(6);

  const { data: ts } = useQuery({
    queryKey: ["dashboard", "timeseries", range] as const,
    queryFn: () =>
      api.get<Timeseries>(`/api/v1/dashboard/timeseries?range=${range}`),
  });

  const totalEncaisse =
    ts?.paidByMonth.reduce((s, m) => s + m.encaisseCents, 0) ?? 0;
  const totalPaid =
    ts?.paidByMonth.reduce((s, m) => s + m.paidCount, 0) ?? 0;
  const dsoMoyen = (() => {
    if (!ts) return 0;
    const months = ts.paidByMonth.filter((m) => m.paidCount > 0);
    if (months.length === 0) return 0;
    return Math.round(
      months.reduce((s, m) => s + m.dsoDays, 0) / months.length,
    );
  })();

  return (
    <div className="flex flex-col gap-6">
      <header className="flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between">
        <div>
          <Eyebrow>Insights</Eyebrow>
          <h1 className="mt-2 font-display text-[28px] font-bold tracking-[-0.022em] text-ink lg:text-[32px]">
            Comprendre vos <em className="text-rubis">flux</em>
          </h1>
          <p className="mt-1.5 text-[14px] text-ink-3 max-w-xl leading-relaxed">
            Vue d'ensemble du portefeuille et des encaissements. Filtre la
            période pour comparer.
          </p>
        </div>

        <RangePicker value={range} onChange={setRange} />
      </header>

      {/* Récap chiffré au-dessus des charts pour ancrer la lecture. */}
      <section
        aria-label="Synthèse de la période"
        className="grid grid-cols-2 gap-3 lg:grid-cols-3 lg:gap-4"
      >
        <SummaryCard
          label={`Encaissé ${range} mois`}
          value={formatEuros(totalEncaisse)}
        />
        <SummaryCard label="Factures payées" value={String(totalPaid)} />
        <SummaryCard
          label={
            <GlossaryTerm definition={GLOSSARY.dso}>DSO moyen</GlossaryTerm>
          }
          value={dsoMoyen > 0 ? `${dsoMoyen} j` : "—"}
        />
      </section>

      {/* Encaissé — pleine largeur, chart le plus important */}
      <Card padding="md">
        <div className="mb-4">
          <Eyebrow tone="ink">
            {ts?.granularity === "week"
              ? "Encaissement hebdomadaire"
              : "Encaissement mensuel"}
          </Eyebrow>
          <p className="mt-1 text-[13px] text-ink-3">
            {ts?.granularity === "week"
              ? "Total encaissé par semaine — la vue 3 mois zoome sur la dynamique récente."
              : "Total facturé encaissé chaque mois sur la période sélectionnée."}
          </p>
        </div>
        <EncaisseChart
          data={ts?.paidByMonth ?? []}
          granularity={ts?.granularity}
          height={300}
        />
      </Card>

      {/* DSO + Pipeline côte à côte */}
      <div className="grid grid-cols-1 gap-4 lg:grid-cols-2 lg:gap-5">
        <Card padding="md">
          <div className="mb-4">
            <Eyebrow tone="ink">
              Délai de paiement (
              <GlossaryTerm definition={GLOSSARY.dso}>DSO</GlossaryTerm>)
            </Eyebrow>
            <p className="mt-1 text-[13px] text-ink-3">
              Jours moyens entre l'émission et le paiement. La référence
              à 30 j est la norme{" "}
              <GlossaryTerm definition={GLOSSARY.lme}>LME</GlossaryTerm> pour le B2B.
            </p>
          </div>
          <DsoTrendChart
            data={ts?.paidByMonth ?? []}
            granularity={ts?.granularity}
            height={260}
          />
        </Card>

        <Card padding="md">
          <div className="mb-4">
            <Eyebrow tone="ink">Pipeline factures</Eyebrow>
            <p className="mt-1 text-[13px] text-ink-3">
              Répartition par statut sur l'ensemble du portefeuille.
            </p>
          </div>
          <div className="grid grid-cols-1 sm:grid-cols-[220px_1fr] gap-4 items-center">
            <PipelineChart
              data={ts?.pipelineByStatus ?? []}
              height={220}
            />
            <PipelineLegend data={ts?.pipelineByStatus ?? []} />
          </div>
        </Card>
      </div>
    </div>
  );
}

function RangePicker({
  value,
  onChange,
}: {
  value: Range;
  onChange: (r: Range) => void;
}) {
  return (
    <div
      role="radiogroup"
      aria-label="Période"
      className="inline-flex rounded-default border border-line bg-white p-0.5 self-start sm:self-end"
    >
      {RANGES.map((r) => {
        const active = r.value === value;
        return (
          <button
            key={r.value}
            type="button"
            role="radio"
            aria-checked={active}
            onClick={() => onChange(r.value)}
            className={cn(
              "px-3 h-8 rounded-default text-[12.5px] font-medium tabular-nums",
              "transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-rubis-glow",
              active
                ? "bg-rubis text-white"
                : "text-ink-2 hover:bg-cream-2",
            )}
          >
            {r.label}
          </button>
        );
      })}
    </div>
  );
}

function SummaryCard({ label, value }: { label: React.ReactNode; value: string }) {
  return (
    <Card padding="md">
      <p className="text-[10.5px] font-semibold uppercase tracking-[0.14em] text-ink-3">
        {label}
      </p>
      <p className="mt-2 font-display text-[24px] font-bold leading-none tracking-[-0.018em] tabular-nums text-ink">
        {value}
      </p>
    </Card>
  );
}
