"use client";

import { useEffect, useMemo, useState } from "react";
import { motion } from "framer-motion";
import { TrendingDown, TrendingUp, Wallet } from "lucide-react";
import { PageHeader } from "@/components/ui/page-header";
import { CustomSelect } from "@/components/ui/custom-select";
import { Button } from "@/components/ui/button";
import { formatMoney } from "@/lib/utils";
import { Valor } from "@/components/ui/valor";
/* O dinheiro desta tela passa pelo <Valor>: quem nao tem a permissao de ver
   valores continua abrindo a tela e trabalhando, com os numeros borrados. */
const dinheiro = (v: number) => <Valor>{formatMoney(v)}</Valor>;

type BankAccountOption = {
  bank_account_id: string;
  name: string | null;
  bank_name: string | null;
  bank_code: string | null;
  active: boolean | null;
};

type DreBreakdownItem = {
  label: string;
  amount: number;
};

type DreDaily = {
  date: string;
  in: number;
  out: number;
  net: number;
};

type DreResponse = {
  ok: true;
  period: {
    start: string;
    end: string;
    label: string;
  };
  kpis: {
    revenue: number;
    expenses: number;
    net: number;
  };
  breakdown: {
    revenue: DreBreakdownItem[];
    expenses: DreBreakdownItem[];
  };
  series: {
    daily: DreDaily[];
  };
};

function formatMonth(value: Date) {
  const year = value.getFullYear();
  const month = String(value.getMonth() + 1).padStart(2, "0");
  return `${year}-${month}`;
}

function formatDateLabel(value: string) {
  return new Intl.DateTimeFormat("pt-BR", {
    day: "2-digit",
    month: "short",
    timeZone: "UTC",
  }).format(new Date(`${value}T00:00:00.000Z`));
}

function formatPercent(value: number) {
  return new Intl.NumberFormat("pt-BR", {
    minimumFractionDigits: 1,
    maximumFractionDigits: 1,
  }).format(value);
}

function normalizeOriginLabel(value: string) {
  return value === "UNKNOWN" ? "Outros" : value;
}

export default function DrePage() {
  const [data, setData] = useState<DreResponse | null>(null);
  const [loading, setLoading] = useState(true);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);
  const [selectedMonth, setSelectedMonth] = useState(() => formatMonth(new Date()));
  const [selectedBank, setSelectedBank] = useState("all");
  const [bankAccounts, setBankAccounts] = useState<BankAccountOption[]>([]);
  const [loadingBanks, setLoadingBanks] = useState(true);
  const [reloadKey, setReloadKey] = useState(0);
  const [activePointIndex, setActivePointIndex] = useState<number | null>(null);

  useEffect(() => {
    let active = true;

    async function loadBankAccounts() {
      setLoadingBanks(true);
      try {
        const response = await fetch("/api/bank-accounts");
        const payload = await response.json();
        if (!response.ok) {
          throw new Error(payload?.error ?? "Falha ao carregar contas bancárias.");
        }
        if (active) {
          setBankAccounts(payload?.accounts ?? []);
        }
      } catch (error) {
        if (active) {
          setErrorMessage(error instanceof Error ? error.message : "Falha ao carregar contas bancárias.");
        }
      } finally {
        if (active) {
          setLoadingBanks(false);
        }
      }
    }

    loadBankAccounts();
    return () => {
      active = false;
    };
  }, []);

  useEffect(() => {
    let active = true;

    async function loadDre() {
      setLoading(true);
      setErrorMessage(null);
      try {
        const params = new URLSearchParams();
        if (selectedMonth) params.set("month", selectedMonth);
        if (selectedBank && selectedBank !== "all") params.set("bank_account_id", selectedBank);
        const response = await fetch(`/api/dre?${params.toString()}`);
        const payload = (await response.json().catch(() => null)) as unknown;
        if (!response.ok) {
          const msg =
            payload &&
            typeof payload === "object" &&
            "message" in payload &&
            typeof (payload as { message?: unknown }).message === "string" &&
            (payload as { message: string }).message.trim()
              ? (payload as { message: string }).message
              : payload &&
                  typeof payload === "object" &&
                  "error" in payload &&
                  typeof (payload as { error?: unknown }).error === "string"
                ? (payload as { error: string }).error
                : "";
          throw new Error(msg || "Falha ao carregar DRE.");
        }
        if (active) {
          setData(payload as DreResponse);
        }
      } catch (error) {
        if (active) {
          setErrorMessage(error instanceof Error ? error.message : "Falha ao carregar DRE.");
        }
      } finally {
        if (active) {
          setLoading(false);
        }
      }
    }

    loadDre();
    return () => {
      active = false;
    };
  }, [selectedMonth, selectedBank, reloadKey]);

  const periodLabel = data?.period.label ?? "Período selecionado";
  const kpis = data?.kpis ?? { revenue: 0, expenses: 0, net: 0 };
  const breakdownRevenue = data?.breakdown.revenue ?? [];
  const breakdownExpenses = data?.breakdown.expenses ?? [];
  const daily = useMemo(() => data?.series.daily ?? [], [data]);

  const isEmpty =
    !loading &&
    !errorMessage &&
    kpis.revenue === 0 &&
    kpis.expenses === 0 &&
    daily.length === 0;

  const demoLines = useMemo(() => {
    return [
      { label: "Receita Bruta", value: kpis.revenue, kind: "revenue" as const },
      { label: "(-) Despesas Operacionais", value: kpis.expenses, kind: "expenses" as const },
      { label: "(=) Resultado Líquido", value: kpis.net, kind: "net" as const },
    ];
  }, [kpis.expenses, kpis.net, kpis.revenue]);

  const demoTotals = useMemo(() => {
    const base = Math.max(kpis.revenue, 1);
    return demoLines.map((line) => {
      if (line.kind === "revenue") return { ...line, percent: 100 };
      if (line.kind === "expenses") return { ...line, percent: (line.value / base) * 100 };
      return { ...line, percent: (line.value / base) * 100 };
    });
  }, [demoLines, kpis.revenue]);

  const chart = useMemo(() => {
    if (daily.length === 0) return null;
    const sorted = [...daily].sort((a, b) => a.date.localeCompare(b.date));
    const values = sorted.map((item) => item.net);
    const min = Math.min(...values, 0);
    const max = Math.max(...values, 0);
    const range = Math.max(max - min, 1);
    const points = values.map((value, index) => {
      const x = values.length === 1 ? 50 : (index / Math.max(values.length - 1, 1)) * 100;
      const y = 100 - ((value - min) / range) * 100;
      return { x, y, value, date: sorted[index].date };
    });
    const linePath = `M ${points.map((point) => `${point.x},${point.y}`).join(" L ")}`;
    const areaPath = `${linePath} L 100,100 L 0,100 Z`;
    return {
      points,
      values,
      linePath,
      areaPath,
    };
  }, [daily]);

  const chartHoverPoint = useMemo(() => {
    if (!chart || activePointIndex === null) return null;
    return chart.points[activePointIndex] ?? null;
  }, [activePointIndex, chart]);

  const bankOptions = useMemo(() => {
    return [
      { value: "all", label: "Todas as contas" },
      ...bankAccounts
        .filter((account) => account.bank_account_id)
        .map((account) => ({
          value: account.bank_account_id,
          label: account.name || account.bank_name || "Conta bancária",
        })),
    ];
  }, [bankAccounts]);

  const kpiCards = useMemo(() => {
    const netPositive = kpis.net >= 0;
    return [
      {
        title: "Receita Bruta",
        value: formatMoney(kpis.revenue),
        icon: TrendingUp,
        accent: "text-[var(--ks-color-primary-strong)]",
        badge: "Entradas",
      },
      {
        title: "Despesas Operacionais",
        value: formatMoney(kpis.expenses),
        icon: TrendingDown,
        accent: "text-[var(--ks-color-primary-strong)]",
        badge: "Saídas",
      },
      {
        title: "Resultado Líquido",
        value: formatMoney(kpis.net),
        icon: Wallet,
        accent: netPositive ? "text-emerald-600" : "text-rose-600",
        badge: netPositive ? "Positivo" : "Negativo",
      },
    ];
  }, [kpis.expenses, kpis.net, kpis.revenue]);

  const extraKpis = useMemo(() => {
    const base = kpis.revenue !== 0 ? kpis.revenue : 1;
    const margin = (kpis.net / base) * 100;
    const daysWithMovement = daily.filter((item) => item.in !== 0 || item.out !== 0).length;
    const ticket = daysWithMovement > 0 ? kpis.net / daysWithMovement : 0;
    return [
      {
        title: "Margem líquida",
        value: `${formatPercent(margin)}%`,
      },
      {
        title: "Ticket médio diário",
        value: formatMoney(ticket),
      },
      {
        title: "Dias com movimento",
        value: String(daysWithMovement),
      },
    ];
  }, [daily, kpis.net, kpis.revenue]);

  return (
    <div className="space-y-6">
      <PageHeader title="DRE" subtitle="Resultado por caixa no período selecionado" />
      <p className="text-sm text-[var(--ks-color-text-muted)]">
        DRE por caixa (baseado nas movimentações em Fluxo de Caixa).
      </p>

      <motion.div
        initial={{ opacity: 0, y: 12 }}
        animate={{ opacity: 1, y: 0 }}
        transition={{ duration: 0.3 }}
        className="ks-surface p-5 rounded-3xl border border-[rgba(99,102,241,0.15)] shadow-[var(--ks-shadow-soft)]"
      >
        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          <div className="space-y-2">
            <label className="text-xs uppercase tracking-[0.2em] text-[var(--ks-color-text-muted)] font-semibold">
              Período
            </label>
            <input
              type="month"
              value={selectedMonth}
              onChange={(event) => setSelectedMonth(event.target.value)}
              className="w-full rounded-xl border border-[rgba(99,102,241,0.2)] bg-white px-3 py-2 text-sm text-[var(--ks-color-text-primary)] focus:outline-none focus:ring-2 focus:ring-[rgba(99,102,241,0.2)] focus:border-[rgba(99,102,241,0.5)]"
            />
            <p className="text-xs text-[var(--ks-color-text-muted)]">{periodLabel}</p>
          </div>
          <div className="space-y-2">
            <label className="text-xs uppercase tracking-[0.2em] text-[var(--ks-color-text-muted)] font-semibold">
              Conta bancária
            </label>
            <CustomSelect
              options={bankOptions}
              value={selectedBank}
              onChange={setSelectedBank}
              placeholder="Selecione uma conta"
            />
            {loadingBanks ? (
              <p className="text-xs text-[var(--ks-color-text-muted)]">Carregando contas...</p>
            ) : null}
          </div>
        </div>
      </motion.div>

      <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
        {loading
          ? Array.from({ length: 3 }).map((_, index) => (
              <div key={index} className="ks-surface p-6 rounded-3xl border border-[rgba(99,102,241,0.08)] animate-pulse">
                <div className="h-4 bg-zinc-200/80 rounded w-2/3 mb-3" />
                <div className="h-8 bg-zinc-200/80 rounded w-1/2" />
              </div>
            ))
          : kpiCards.map((item, index) => (
              <motion.div
                key={item.title}
                initial={{ opacity: 0, y: 10 }}
                animate={{ opacity: 1, y: 0 }}
                transition={{ duration: 0.3, delay: index * 0.05 }}
                className="ks-surface p-6 rounded-3xl border border-[rgba(99,102,241,0.12)] shadow-[var(--ks-shadow-soft)]"
              >
                <div className="flex items-center justify-between">
                  <div className="w-10 h-10 rounded-2xl bg-[rgba(99,102,241,0.1)] flex items-center justify-center">
                    <item.icon className={`w-5 h-5 ${item.accent}`} />
                  </div>
                  <span className="text-[0.65rem] uppercase tracking-[0.3em] text-[var(--ks-color-text-muted)]">
                    {item.badge}
                  </span>
                </div>
                <p className="mt-4 text-xs uppercase tracking-[0.2em] text-[var(--ks-color-text-muted)] font-semibold">
                  {item.title}
                </p>
                <p className={`mt-3 text-2xl font-semibold text-[var(--ks-color-text-primary)] ${item.accent}`}>
                  {item.value}
                </p>
              </motion.div>
            ))}
      </div>

      <div className="grid grid-cols-1 md:grid-cols-3 gap-3">
        {loading
          ? Array.from({ length: 3 }).map((_, index) => (
              <div key={index} className="ks-surface p-4 rounded-2xl border border-[rgba(99,102,241,0.08)] animate-pulse">
                <div className="h-3 bg-zinc-200/80 rounded w-1/2 mb-2" />
                <div className="h-5 bg-zinc-200/80 rounded w-1/3" />
              </div>
            ))
          : extraKpis.map((item) => (
              <div
                key={item.title}
                className="ks-surface p-4 rounded-2xl border border-[rgba(99,102,241,0.08)]"
              >
                <p className="text-xs uppercase tracking-[0.2em] text-[var(--ks-color-text-muted)] font-semibold">
                  {item.title}
                </p>
                <p className="mt-2 text-lg font-semibold text-[var(--ks-color-text-primary)]">{item.value}</p>
              </div>
            ))}
      </div>

      {errorMessage ? (
        <div className="ks-surface p-8 rounded-3xl border border-[rgba(99,102,241,0.12)] text-center">
          <p className="text-[var(--ks-color-text-primary)] font-semibold">
            Não foi possível carregar o DRE.
          </p>
          <p className="text-sm text-[var(--ks-color-text-muted)] mt-2">{errorMessage}</p>
          <div className="mt-4 flex justify-center">
            <Button type="button" onClick={() => setReloadKey((prev) => prev + 1)}>
              Tentar novamente
            </Button>
          </div>
        </div>
      ) : null}

      {isEmpty ? (
        <div className="ks-surface p-8 rounded-3xl border border-[rgba(99,102,241,0.12)] text-center">
          <p className="text-[var(--ks-color-text-primary)] font-semibold">Sem movimentações no período selecionado</p>
          <p className="text-sm text-[var(--ks-color-text-muted)] mt-2">
            Selecione outro mês ou conta para visualizar o DRE.
          </p>
        </div>
      ) : null}

      {!loading && !errorMessage && !isEmpty ? (
        <>
          <div className="grid grid-cols-1 lg:grid-cols-[1.2fr_1fr] gap-6">
            <motion.div
              initial={{ opacity: 0, y: 12 }}
              animate={{ opacity: 1, y: 0 }}
              transition={{ duration: 0.35 }}
              className="ks-surface p-6 rounded-3xl border border-[rgba(99,102,241,0.12)] shadow-[var(--ks-shadow-soft)] space-y-4"
            >
              <div>
                <p className="text-xs uppercase tracking-[0.2em] text-[var(--ks-color-text-muted)] font-semibold">
                  Demonstrativo gerencial
                </p>
                <p className="text-sm text-[var(--ks-color-text-muted)] mt-1">
                  Receita, despesas e resultado do período por caixa.
                </p>
              </div>
              <div className="space-y-3">
                {demoTotals.map((item) => {
                  const accent =
                    item.kind === "net"
                      ? item.value >= 0
                        ? "text-emerald-600"
                        : "text-rose-600"
                      : "text-[var(--ks-color-primary-strong)]";
                  const percentLabel = item.kind === "revenue" ? "100,0%" : `${formatPercent(item.percent)}%`;
                  const progress = Math.min(100, Math.abs(item.percent));
                  return (
                    <div key={item.label} className="grid grid-cols-1 gap-2">
                      <div className="flex items-center justify-between">
                        <div className="space-y-0.5">
                          <p className="text-sm font-medium text-[var(--ks-color-text-primary)]">{item.label}</p>
                          <p className="text-xs text-[var(--ks-color-text-muted)]">{percentLabel} da receita</p>
                        </div>
                        <p className={`text-sm font-semibold ${accent}`}>{dinheiro(item.value)}</p>
                      </div>
                      <div className="h-1 rounded-full bg-[rgba(99,102,241,0.12)] overflow-hidden">
                        <div
                          className="h-full rounded-full bg-[rgba(99,102,241,0.45)]"
                          style={{ width: `${progress}%` }}
                        />
                      </div>
                    </div>
                  );
                })}
              </div>
            </motion.div>

            <motion.div
              initial={{ opacity: 0, y: 12 }}
              animate={{ opacity: 1, y: 0 }}
              transition={{ duration: 0.35 }}
              className="ks-surface p-6 rounded-3xl border border-[rgba(99,102,241,0.12)] shadow-[var(--ks-shadow-soft)]"
            >
              <div className="flex items-center justify-between">
                <div>
                  <p className="text-xs uppercase tracking-[0.2em] text-[var(--ks-color-text-muted)] font-semibold">
                    Evolução no mês
                  </p>
                  <p className="text-sm text-[var(--ks-color-text-muted)] mt-1">
                    Resultado líquido diário.
                  </p>
                </div>
                <p className={`text-sm font-semibold ${kpis.net >= 0 ? "text-emerald-600" : "text-rose-600"}`}>
                  {dinheiro(kpis.net)}
                </p>
              </div>
              <div className="mt-6 h-44 relative">
                {chart ? (
                  <svg
                    viewBox="0 0 100 100"
                    preserveAspectRatio="none"
                    className="w-full h-full"
                    onMouseLeave={() => setActivePointIndex(null)}
                    onMouseMove={(event) => {
                      if (!chart) return;
                      const bounds = event.currentTarget.getBoundingClientRect();
                      const x = ((event.clientX - bounds.left) / bounds.width) * 100;
                      const closestIndex = chart.points.reduce((acc, point, index) => {
                        const current = Math.abs(point.x - x);
                        return current < acc.distance ? { index, distance: current } : acc;
                      }, { index: 0, distance: Infinity });
                      setActivePointIndex(closestIndex.index);
                    }}
                  >
                    <defs>
                      <linearGradient id="dre-net-gradient" x1="0" y1="0" x2="0" y2="1">
                        <stop offset="0%" stopColor="rgba(99,102,241,0.28)" />
                        <stop offset="100%" stopColor="rgba(99,102,241,0.03)" />
                      </linearGradient>
                    </defs>
                    <path d={chart.areaPath} fill="url(#dre-net-gradient)" />
                    <path
                      d={chart.linePath}
                      fill="none"
                      stroke="rgb(99,102,241)"
                      strokeWidth="2"
                      strokeLinecap="round"
                      strokeLinejoin="round"
                    />
                    {chartHoverPoint ? (
                      <circle
                        cx={chartHoverPoint.x}
                        cy={chartHoverPoint.y}
                        r="2.6"
                        fill="rgb(99,102,241)"
                        stroke="white"
                        strokeWidth="1.5"
                      />
                    ) : null}
                  </svg>
                ) : (
                  <div className="h-full flex items-center justify-center text-sm text-[var(--ks-color-text-muted)]">
                    Sem dados para o gráfico.
                  </div>
                )}
                {chartHoverPoint ? (
                  <div
                    className="absolute top-3 right-4 rounded-2xl border border-[rgba(99,102,241,0.2)] bg-white/95 shadow-[var(--ks-shadow-soft)] px-3 py-2"
                  >
                    <p className="text-[0.7rem] uppercase tracking-[0.2em] text-[var(--ks-color-text-muted)]">
                      {formatDateLabel(chartHoverPoint.date)}
                    </p>
                    <p className="text-sm font-semibold text-[var(--ks-color-text-primary)]">
                      {dinheiro(chartHoverPoint.value)}
                    </p>
                  </div>
                ) : null}
              </div>
              {chart ? (
                <div className="mt-4 flex items-center justify-between text-xs text-[var(--ks-color-text-muted)]">
                  <span>{formatDateLabel(chart.points[0].date)}</span>
                  <span>{formatDateLabel(chart.points[chart.points.length - 1].date)}</span>
                </div>
              ) : null}
            </motion.div>
          </div>

          <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
            <motion.div
              initial={{ opacity: 0, y: 12 }}
              animate={{ opacity: 1, y: 0 }}
              transition={{ duration: 0.35 }}
              className="ks-surface p-6 rounded-3xl border border-[rgba(99,102,241,0.12)] shadow-[var(--ks-shadow-soft)]"
            >
              <div className="flex items-center justify-between">
                <div>
                  <p className="text-xs uppercase tracking-[0.2em] text-[var(--ks-color-text-muted)] font-semibold">
                    Receitas por origem
                  </p>
                  <p className="text-sm text-[var(--ks-color-text-muted)] mt-1">
                    Top 6 itens do período.
                  </p>
                </div>
                <p className="text-sm font-semibold text-[var(--ks-color-primary-strong)]">
                  {dinheiro(kpis.revenue)}
                </p>
              </div>
              <div className="mt-4 space-y-3">
                {breakdownRevenue.length === 0 ? (
                  <p className="text-sm text-[var(--ks-color-text-muted)]">Nenhuma receita registrada.</p>
                ) : (
                  breakdownRevenue.slice(0, 6).map((item) => {
                    const percent = kpis.revenue > 0 ? (item.amount / kpis.revenue) * 100 : 0;
                    return (
                      <div key={item.label} className="flex items-center justify-between">
                        <div>
                          <p className="text-sm font-medium text-[var(--ks-color-text-primary)]">
                            {normalizeOriginLabel(item.label)}
                          </p>
                          <p className="text-xs text-[var(--ks-color-text-muted)]">{formatPercent(percent)}%</p>
                        </div>
                        <p className="text-sm font-semibold text-[var(--ks-color-primary-strong)]">
                          {dinheiro(item.amount)}
                        </p>
                      </div>
                    );
                  })
                )}
              </div>
            </motion.div>

            <motion.div
              initial={{ opacity: 0, y: 12 }}
              animate={{ opacity: 1, y: 0 }}
              transition={{ duration: 0.35 }}
              className="ks-surface p-6 rounded-3xl border border-[rgba(99,102,241,0.12)] shadow-[var(--ks-shadow-soft)]"
            >
              <div className="flex items-center justify-between">
                <div>
                  <p className="text-xs uppercase tracking-[0.2em] text-[var(--ks-color-text-muted)] font-semibold">
                    Despesas por origem
                  </p>
                  <p className="text-sm text-[var(--ks-color-text-muted)] mt-1">
                    Top 6 itens do período.
                  </p>
                </div>
                <p className="text-sm font-semibold text-[var(--ks-color-primary-strong)]">
                  {dinheiro(kpis.expenses)}
                </p>
              </div>
              <div className="mt-4 space-y-3">
                {breakdownExpenses.length === 0 ? (
                  <p className="text-sm text-[var(--ks-color-text-muted)]">Nenhuma despesa registrada.</p>
                ) : (
                  breakdownExpenses.slice(0, 6).map((item) => {
                    const percent = kpis.expenses > 0 ? (item.amount / kpis.expenses) * 100 : 0;
                    return (
                      <div key={item.label} className="flex items-center justify-between">
                        <div>
                          <p className="text-sm font-medium text-[var(--ks-color-text-primary)]">
                            {normalizeOriginLabel(item.label)}
                          </p>
                          <p className="text-xs text-[var(--ks-color-text-muted)]">{formatPercent(percent)}%</p>
                        </div>
                        <p className="text-sm font-semibold text-[var(--ks-color-primary-strong)]">
                          {dinheiro(item.amount)}
                        </p>
                      </div>
                    );
                  })
                )}
              </div>
            </motion.div>
          </div>
        </>
      ) : null}
    </div>
  );
}
