import { useCallback, useEffect, useMemo, useState } from "react";
import { format, startOfDay } from "date-fns";
import { ptBR } from "date-fns/locale";
import { CalendarIcon, ChevronDown, LayoutDashboard, Loader2, RefreshCw, Sparkles } from "lucide-react";
import { motion } from "motion/react";
import { Cell, Legend, Pie, PieChart, ResponsiveContainer, Tooltip } from "recharts";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Checkbox } from "@/components/ui/checkbox";
import { Label } from "@/components/ui/label";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { ScrollArea } from "@/components/ui/scroll-area";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Separator } from "@/components/ui/separator";
import { useAuthAccess } from "@/contexts/AuthAccessContext";
import {
  dashboardPontosPorClienteService,
  type DashboardPontosPorParceiro,
} from "@/services/fechamento/dashboardPontosPorCliente";
import { fechamentoParceirosService, type ParceiroItem } from "@/services/fechamento/parceiros";
import { cn } from "@/lib/utils";

function formatPontos(valor: number): string {
  return valor.toLocaleString("pt-BR", { minimumFractionDigits: 0, maximumFractionDigits: 4 });
}

/** Primeiro dia do mês civil (hora local). */
function inicioDoMesAtual(ref = new Date()): Date {
  return new Date(ref.getFullYear(), ref.getMonth(), 1);
}

/** Último dia do mês civil (hora local). */
function fimDoMesAtual(ref = new Date()): Date {
  return new Date(ref.getFullYear(), ref.getMonth() + 1, 0);
}

function dateToApiYmd(d: Date): string {
  return format(d, "yyyy-MM-dd");
}

function sliceColor(i: number): string {
  const hue = (i * 47 + 198) % 360;
  return `hsl(${hue} 72% ${52 - (i % 4) * 4}%)`;
}

function DistribuicaoClientesDonut({ bloco }: { bloco: DashboardPontosPorParceiro }) {
  const total = bloco.totalParceiro > 0 ? bloco.totalParceiro : 1;
  const data = useMemo(
    () =>
      bloco.linhas.map((l) => ({
        name: l.cliente,
        value: l.pontos,
      })),
    [bloco.linhas],
  );

  if (data.length === 0) {
    return (
      <div className="flex h-[220px] items-center justify-center text-sm text-muted-foreground">
        Sem clientes neste período.
      </div>
    );
  }

  return (
    <div className="h-[min(320px,55vw)] w-full min-h-[220px] min-w-0">
      <ResponsiveContainer width="100%" height="100%">
        <PieChart>
          <Pie
            data={data}
            cx="50%"
            cy="48%"
            innerRadius="42%"
            outerRadius="72%"
            paddingAngle={2}
            dataKey="value"
            nameKey="name"
            stroke="hsl(var(--border))"
            strokeWidth={1}
            label={({ name, percent }) =>
              (percent ?? 0) >= 0.06
                ? `${String(name).slice(0, 14)}${String(name).length > 14 ? "…" : ""} ${(((percent ?? 0) as number) * 100).toFixed(0)}%`
                : ""
            }
            labelLine={false}
          >
            {data.map((_, i) => (
              <Cell key={`${bloco.parceiroId}-${i}`} fill={sliceColor(i)} />
            ))}
          </Pie>
          <Tooltip
            content={({ active, payload }) => {
              if (!active || !payload?.[0]) return null;
              const row = payload[0].payload as { name: string; value: number };
              const pct = total > 0 ? (row.value / total) * 100 : 0;
              return (
                <div className="rounded-lg border border-border/80 bg-background/95 px-3 py-2 text-xs shadow-lg backdrop-blur">
                  <p className="font-medium">{row.name}</p>
                  <p className="tabular-nums text-muted-foreground">
                    {formatPontos(row.value)} pts · {pct.toFixed(1)}%
                  </p>
                </div>
              );
            }}
          />
          <Legend
            verticalAlign="bottom"
            height={44}
            formatter={(value) => (
              <span className="text-[11px] text-muted-foreground">{String(value).slice(0, 28)}</span>
            )}
            wrapperStyle={{ paddingTop: 4 }}
          />
        </PieChart>
      </ResponsiveContainer>
    </div>
  );
}

export default function DashboardPontos() {
  const { papel, me } = useAuthAccess();
  const [parceiros, setParceiros] = useState<ParceiroItem[]>([]);
  const [dataInicio, setDataInicio] = useState(() => inicioDoMesAtual());
  const [dataFim, setDataFim] = useState(() => fimDoMesAtual());
  /** `null` = todos os parceiros (sem filtro na API). */
  const [selectedPartnerIds, setSelectedPartnerIds] = useState<string[] | null>(null);
  const [parceirosMenuOpen, setParceirosMenuOpen] = useState(false);
  const [loading, setLoading] = useState(true);
  const [dados, setDados] = useState<DashboardPontosPorParceiro[]>([]);

  const parceiroFixoSupervisor = papel === "supervisor" && me?.parceiroId;

  const selectionKey = selectedPartnerIds === null ? "all" : [...selectedPartnerIds].sort().join(",");
  const periodoKey = `${dataInicio.getTime()}-${dataFim.getTime()}`;

  const loadParceiros = useCallback(async () => {
    if (parceiroFixoSupervisor && me?.parceiroId) {
      try {
        const res = await fechamentoParceirosService.listarParceiros({
          estaAtivo: "all",
          page: 1,
          perPage: 200,
        });
        const um = res.data.find((p) => p.id === me.parceiroId);
        setParceiros(um ? [um] : []);
      } catch (e) {
        const message = e instanceof Error ? e.message : "Erro ao carregar parceiros.";
        toast.error(message);
        setParceiros([]);
      }
      return;
    }
    try {
      const lista = await fechamentoParceirosService.listarParceirosAtivos();
      setParceiros(lista);
    } catch (e) {
      const message = e instanceof Error ? e.message : "Erro ao carregar parceiros.";
      toast.error(message);
      setParceiros([]);
    }
  }, [me?.parceiroId, parceiroFixoSupervisor]);

  const loadRelatorio = useCallback(async () => {
    try {
      setLoading(true);
      let parceiroIds: string[] | undefined;
      if (parceiroFixoSupervisor && me?.parceiroId) {
        parceiroIds = [me.parceiroId];
      } else if (selectedPartnerIds !== null && selectedPartnerIds.length > 0) {
        parceiroIds = selectedPartnerIds;
      }
      if (startOfDay(dataFim) < startOfDay(dataInicio)) {
        toast.error("A data final não pode ser anterior à inicial.");
        setDados([]);
        return;
      }
      const res = await dashboardPontosPorClienteService.relatorioPontosPorCliente({
        dataInicio: dateToApiYmd(dataInicio),
        dataFim: dateToApiYmd(dataFim),
        parceiroIds,
      });
      setDados(res);
    } catch (e) {
      const message = e instanceof Error ? e.message : "Erro ao carregar dashboard.";
      toast.error(message);
      setDados([]);
    } finally {
      setLoading(false);
    }
  }, [dataFim, dataInicio, me?.parceiroId, parceiroFixoSupervisor, periodoKey, selectionKey]);

  useEffect(() => {
    void loadParceiros();
  }, [loadParceiros]);

  useEffect(() => {
    void loadRelatorio();
  }, [loadRelatorio, me?.parceiroId, papel]);

  const allParceiroIds = useMemo(() => parceiros.map((p) => p.id), [parceiros]);

  const parceirosSelecaoLabel = useMemo(() => {
    if (parceiroFixoSupervisor) {
      const p = parceiros[0];
      if (!p) return "Parceiro vinculado";
      return p.codinome?.trim() ? `${p.nome} (${p.codinome.trim()})` : p.nome;
    }
    if (selectedPartnerIds === null) return "Todos os parceiros";
    if (selectedPartnerIds.length === 1) {
      const p = parceiros.find((x) => x.id === selectedPartnerIds[0]);
      if (!p) return "1 parceiro";
      return p.codinome?.trim() ? `${p.nome} (${p.codinome.trim()})` : p.nome;
    }
    return `${selectedPartnerIds.length} parceiros selecionados`;
  }, [parceiroFixoSupervisor, parceiros, selectedPartnerIds]);

  const toggleParceiro = useCallback(
    (id: string, checked: boolean) => {
      setSelectedPartnerIds((prev) => {
        if (parceiroFixoSupervisor) return prev;
        if (prev === null) {
          if (checked) return null;
          const next = allParceiroIds.filter((x) => x !== id);
          if (next.length === 0) {
            toast.error("Selecione ao menos um parceiro.");
            return prev;
          }
          return next;
        }
        const set = new Set(prev);
        if (checked) set.add(id);
        else set.delete(id);
        const arr = Array.from(set);
        if (arr.length === 0) {
          toast.error("Selecione ao menos um parceiro.");
          return prev;
        }
        if (arr.length === allParceiroIds.length) return null;
        return arr;
      });
    },
    [allParceiroIds, parceiroFixoSupervisor],
  );

  const setTodosParceiros = useCallback(() => {
    if (!parceiroFixoSupervisor) setSelectedPartnerIds(null);
  }, [parceiroFixoSupervisor]);

  const isParceiroChecked = (id: string) =>
    selectedPartnerIds === null || (selectedPartnerIds?.includes(id) ?? false);

  return (
    <div className="relative mx-auto max-w-7xl space-y-8 p-4 pb-14 lg:p-8">
      <div className="pointer-events-none absolute inset-x-0 top-0 h-64 bg-gradient-to-b from-primary/12 via-primary/5 to-transparent blur-3xl" />

      <motion.div
        initial={{ opacity: 0, y: 10 }}
        animate={{ opacity: 1, y: 0 }}
        transition={{ duration: 0.35 }}
        className="relative flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between sm:gap-6"
      >
        <div className="space-y-2">
          <div className="inline-flex items-center gap-2 rounded-full border border-primary/25 bg-primary/10 px-3 py-1 text-xs font-medium text-primary">
            <Sparkles className="h-3.5 w-3.5" />
            Intelligence Score
          </div>
          <h1 className="flex items-center gap-3 text-3xl font-bold tracking-tight md:text-4xl">
            <span className="flex h-12 w-12 items-center justify-center rounded-2xl bg-primary/15 text-primary shadow-inner cyber-glow">
              <LayoutDashboard className="h-6 w-6" />
            </span>
            Dashboard
          </h1>
          <p className="max-w-xl text-sm text-muted-foreground">
            Distribuição de pontos por cliente — visão rápida do que cada parceiro entregou no período.
          </p>
        </div>
        <Button
          type="button"
          variant="outline"
          size="sm"
          className="gap-2 self-start border-primary/20 bg-background/80 shadow-sm backdrop-blur"
          onClick={() => void loadRelatorio()}
        >
          <RefreshCw className={cn("h-4 w-4", loading && "animate-spin")} />
          Atualizar
        </Button>
      </motion.div>

      <motion.div
        initial={{ opacity: 0, y: 12 }}
        animate={{ opacity: 1, y: 0 }}
        transition={{ duration: 0.4, delay: 0.05 }}
      >
        <Card className="overflow-hidden border-primary/10 shadow-xl">
          <CardHeader className="border-b border-border/60 bg-muted/30 pb-4">
            <CardTitle className="text-lg">Filtros</CardTitle>
          </CardHeader>
          <CardContent className="grid grid-cols-1 gap-4 pt-6 sm:grid-cols-2 sm:items-end lg:grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1.25fr)_auto] lg:gap-5">
            <div className="flex min-w-0 flex-col gap-2">
              <Label className="text-[11px] font-semibold uppercase leading-tight tracking-wide text-muted-foreground sm:text-xs">
                Data inicial
              </Label>
              <Popover>
                <PopoverTrigger asChild>
                  <Button
                    type="button"
                    variant="outline"
                    className="h-11 w-full min-w-0 justify-start gap-2 text-left text-sm font-normal tabular-nums"
                  >
                    <CalendarIcon className="h-4 w-4 shrink-0" />
                    <span className="min-w-0 truncate">{format(dataInicio, "dd/MM/yyyy", { locale: ptBR })}</span>
                  </Button>
                </PopoverTrigger>
                <PopoverContent className="w-auto p-0" align="start">
                  <Calendar
                    mode="single"
                    selected={dataInicio}
                    onSelect={(d) => {
                      if (d) setDataInicio(d);
                    }}
                    locale={ptBR}
                    defaultMonth={dataInicio}
                    initialFocus
                    className="pointer-events-auto p-3"
                  />
                </PopoverContent>
              </Popover>
            </div>

            <div className="flex min-w-0 flex-col gap-2">
              <Label className="text-[11px] font-semibold uppercase leading-tight tracking-wide text-muted-foreground sm:text-xs">
                Data final
              </Label>
              <Popover>
                <PopoverTrigger asChild>
                  <Button
                    type="button"
                    variant="outline"
                    className="h-11 w-full min-w-0 justify-start gap-2 text-left text-sm font-normal tabular-nums"
                  >
                    <CalendarIcon className="h-4 w-4 shrink-0" />
                    <span className="min-w-0 truncate">{format(dataFim, "dd/MM/yyyy", { locale: ptBR })}</span>
                  </Button>
                </PopoverTrigger>
                <PopoverContent className="w-auto p-0" align="start">
                  <Calendar
                    mode="single"
                    selected={dataFim}
                    onSelect={(d) => {
                      if (d) setDataFim(d);
                    }}
                    locale={ptBR}
                    defaultMonth={dataFim}
                    disabled={(date) => date < startOfDay(dataInicio)}
                    initialFocus
                    className="pointer-events-auto p-3"
                  />
                </PopoverContent>
              </Popover>
            </div>

            {!parceiroFixoSupervisor ? (
              <div className="flex min-w-0 flex-col gap-2 sm:col-span-2 lg:col-span-1">
                <Label className="text-[11px] font-semibold uppercase leading-tight tracking-wide text-muted-foreground sm:text-xs">
                  Parceiros
                </Label>
                <Popover open={parceirosMenuOpen} onOpenChange={setParceirosMenuOpen}>
                  <PopoverTrigger asChild>
                    <Button
                      type="button"
                      variant="outline"
                      role="combobox"
                      aria-expanded={parceirosMenuOpen}
                      className="h-11 w-full min-w-0 justify-between gap-2 font-normal"
                    >
                      <span className="min-w-0 truncate text-left text-sm">{parceirosSelecaoLabel}</span>
                      <ChevronDown className="h-4 w-4 shrink-0 opacity-60" />
                    </Button>
                  </PopoverTrigger>
                  <PopoverContent
                    className="w-[min(100vw-2rem,var(--radix-popover-trigger-width))] max-w-md p-0"
                    align="start"
                  >
                    <div className="space-y-2 border-b border-border/60 p-3">
                      <span className="text-sm font-semibold">Selecionar parceiros</span>
                      <div className="flex items-center gap-2 rounded-lg px-1 py-1 hover:bg-muted/50">
                        <Checkbox
                          id="par-todos"
                          checked={selectedPartnerIds === null}
                          onCheckedChange={(c) => {
                            if (c === true) {
                              setTodosParceiros();
                              return;
                            }
                            if (allParceiroIds.length <= 1) return;
                            setSelectedPartnerIds([allParceiroIds[0]]);
                            toast.info("Filtro por um parceiro. Use «Todos» para voltar a exibir todos.");
                          }}
                        />
                        <label htmlFor="par-todos" className="cursor-pointer text-sm font-medium">
                          Todos os parceiros
                        </label>
                      </div>
                    </div>
                    <Separator />
                    <ScrollArea className="h-[220px]">
                      <div className="space-y-1 p-3">
                        {parceiros.map((p) => (
                          <div
                            key={p.id}
                            className="flex items-center gap-2 rounded-lg px-1 py-1.5 hover:bg-muted/50"
                          >
                            <Checkbox
                              id={`par-${p.id}`}
                              checked={isParceiroChecked(p.id)}
                              onCheckedChange={(c) => toggleParceiro(p.id, c === true)}
                            />
                            <label htmlFor={`par-${p.id}`} className="flex-1 cursor-pointer truncate text-sm">
                              {p.codinome?.trim() ? `${p.nome} (${p.codinome.trim()})` : p.nome}
                            </label>
                          </div>
                        ))}
                      </div>
                    </ScrollArea>
                  </PopoverContent>
                </Popover>
              </div>
            ) : (
              <div className="flex min-w-0 flex-col gap-2 sm:col-span-2 lg:col-span-1">
                <Label className="text-[11px] font-semibold uppercase leading-tight tracking-wide text-muted-foreground sm:text-xs">
                  Parceiro
                </Label>
                <Select disabled value={me?.parceiroId ?? ""}>
                  <SelectTrigger className="h-11 w-full min-w-0">
                    <SelectValue placeholder="Parceiro vinculado" />
                  </SelectTrigger>
                  <SelectContent>
                    {parceiros.map((p) => (
                      <SelectItem key={p.id} value={p.id}>
                        {p.codinome?.trim() ? `${p.nome} (${p.codinome.trim()})` : p.nome}
                      </SelectItem>
                    ))}
                    {parceiros.length === 0 && me?.parceiroId ? (
                      <SelectItem value={me.parceiroId}>Parceiro vinculado</SelectItem>
                    ) : null}
                  </SelectContent>
                </Select>
              </div>
            )}

            <div className="flex items-end sm:col-span-2 lg:col-span-1">
              <Button type="button" className="h-11 w-full sm:w-auto lg:w-full" onClick={() => void loadRelatorio()}>
                Aplicar
              </Button>
            </div>
          </CardContent>
        </Card>
      </motion.div>

      {loading && dados.length === 0 ? (
        <div className="flex justify-center py-24">
          <Loader2 className="h-12 w-12 animate-spin text-primary/60" />
        </div>
      ) : dados.length === 0 ? (
        <Card className="border-dashed">
          <CardContent className="py-16 text-center text-muted-foreground">
            Nenhum dado para os filtros atuais. Ajuste o período ou os parceiros.
          </CardContent>
        </Card>
      ) : (
        <motion.div
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          transition={{ duration: 0.35 }}
          className="grid grid-cols-1 gap-4 sm:gap-6 lg:grid-cols-2"
        >
          {dados.map((bloco, idx) => (
            <motion.div
              key={bloco.parceiroId}
              initial={{ opacity: 0, y: 16 }}
              animate={{ opacity: 1, y: 0 }}
              transition={{ duration: 0.35, delay: Math.min(idx * 0.06, 0.35) }}
            >
              <Card className="h-full overflow-hidden border-border/80 bg-card/95 shadow-lg transition-shadow hover:shadow-xl">
                <CardHeader className="border-b border-border/50 bg-gradient-to-r from-primary/8 to-transparent pb-4">
                  <div className="flex min-w-0 flex-col gap-3 sm:flex-row sm:items-center sm:justify-between sm:gap-4">
                    <CardTitle
                      className="min-w-0 max-w-full flex-1 truncate text-left text-base font-semibold leading-snug sm:text-lg"
                      title={bloco.parceiroNome}
                    >
                      {bloco.parceiroNome}
                    </CardTitle>
                    <span className="inline-flex w-fit shrink-0 self-start rounded-full bg-primary/15 px-3 py-1.5 text-sm font-semibold tabular-nums text-primary sm:self-center">
                      {formatPontos(bloco.totalParceiro)} pts
                    </span>
                  </div>
                </CardHeader>
                <CardContent className="pt-6">
                  <DistribuicaoClientesDonut bloco={bloco} />
                </CardContent>
              </Card>
            </motion.div>
          ))}
        </motion.div>
      )}
    </div>
  );
}
