"use client";

import { useEffect, useState } from "react";
import { DollarSign, TrendingUp, TrendingDown, CreditCard, Calendar, Package, Check, Clock } from "lucide-react";
import { PageHeader } from "@/components/ui/page-header";
import { getSupabaseClient } from "@/lib/supabase";
import { getCompanyContext } from "@/lib/company-context";
import { Valor } from "@/components/ui/valor";
import { janelaDoMesAnterior, nomeDoMes, parteDoTotal, somaDasFatias, variacaoDoMes } from "@/lib/parte-do-total";

const MANUAL_PREFIX = "[MANUAL] ";

interface FinancialMetrics {
  totalReceivedToday: number;
  totalReceivedThisMonth: number;
  /* Só para a variação do cartão do mês: o mesmo pedaço do mês anterior. */
  totalReceivedPrevMonth: number;
  totalOpenAmount: number;
  paidOrders: number;
  pendingOrders: number;
  paymentMethodStats: {
    method: string;
    count: number;
    amount: number;
  }[];
  manualInTotal: number;
  manualInCount: number;
  ordersInTotal: number;
  ordersInCount: number;
}

interface StatCardProps {
  title: string;
  /* Node, e nao string: o valor pode chegar embrulhado no <Valor>, que borra
     o numero para quem nao tem permissao de ver dinheiro. */
  value: React.ReactNode;
  icon: React.ComponentType<{ className?: string }>;
  description?: string;
  trend?: {
    value: string;
    isPositive: boolean;
  };
}

function isCanceledOrderStatus(status: unknown) {
  const normalized = String(status || "").trim().toLowerCase();
  return normalized === "canceled" || normalized === "cancelled";
}

function isManualTagged(description: unknown) {
  return typeof description === "string" && description.startsWith(MANUAL_PREFIX);
}

function normalizeFlowOrigin(origin: unknown, description: unknown) {
  if (origin === "MANUAL") return "MANUAL";
  if (origin === "AJUSTE" && isManualTagged(description)) return "MANUAL";
  return String(origin || "").trim().toUpperCase();
}

function paymentMethodLabel(method: string) {
  switch (method) {
    case "pix":
      return "Pix";
    case "credit_card":
      return "Cartão Crédito";
    case "debit_card":
      return "Cartão Débito";
    case "cash":
      return "Dinheiro";
    case "transfer":
      return "Transferência";
    case "manual":
      return "Lançamento manual";
    /* "N/A" era o nome disto aqui e "Sem forma de pagamento" no DRE
       Analítico: a mesma entrada com dois nomes em duas telas vizinhas. Cai
       aqui o ajuste de saldo e o pagamento gravado sem meio. */
    default:
      return "Sem forma de pagamento";
  }
}

function StatCard({ title, value, icon: Icon, description, trend }: StatCardProps) {
  return (
    <div className="ks-surface p-6 rounded-xl">
      <div className="flex items-center justify-between mb-4">
        <div className="p-2 bg-[var(--ks-color-primary-light)] rounded-lg">
          <Icon className="w-5 h-5 text-[var(--ks-color-primary)]" />
        </div>
        {trend && (
          <div className={`flex items-center gap-1 text-sm ${trend.isPositive ? 'text-green-600' : 'text-red-600'}`}>
            {trend.isPositive ? <TrendingUp size={14} /> : <TrendingDown size={14} />}
            {trend.value}
          </div>
        )}
      </div>
      
      <div className="space-y-1">
        <h3 className="text-2xl font-bold text-[var(--ks-color-text-primary)]">{value}</h3>
        <p className="text-sm text-[var(--ks-color-text-muted)]">{title}</p>
        {description && (
          <p className="text-xs text-[var(--ks-color-text-soft)]">{description}</p>
        )}
      </div>
    </div>
  );
}

export default function FinancialOverview() {
  const [metrics, setMetrics] = useState<FinancialMetrics | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetchFinancialMetrics();
  }, []);

  async function fetchFinancialMetrics() {
    try {
      const supabase = getSupabaseClient();
      const {
        data: { user },
      } = await supabase.auth.getUser();
      if (!user) {
        setMetrics(null);
        setLoading(false);
        return;
      }

      const ctx = await getCompanyContext(supabase, user);
      const tenantIds = ctx.tenantIds?.length ? ctx.tenantIds : [user.id];
      
      // Obter movimentações financeiras (inclui pedidos e lançamentos manuais)
      const { data: flowData } = await supabase
        .from("cash_flow")
        .select("date,type,origin,amount,reference_id,description")
        .eq("company_id", ctx.companyId)
        .order("date", { ascending: false });

      // Obter dados dos pedidos
      const { data: ordersData } = await supabase
        .from('orders')
        .select('id, status, total_amount, paid_amount, financial_status')
        .in('user_id', tenantIds);

      if (!flowData || !ordersData) return;

      const startOfDay = (date: Date) => {
        const d = new Date(date);
        d.setHours(0, 0, 0, 0);
        return d;
      };

      const addDays = (date: Date, days: number) => {
        const d = new Date(date);
        d.setDate(d.getDate() + days);
        return d;
      };

      const parsePaymentDate = (value: unknown): Date | null => {
        if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value;
        if (typeof value !== "string") return null;

        const dateOnly = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
        if (dateOnly) {
          const year = Number(dateOnly[1]);
          const month = Number(dateOnly[2]);
          const day = Number(dateOnly[3]);
          const d = new Date(year, month - 1, day, 0, 0, 0, 0);
          return Number.isNaN(d.getTime()) ? null : d;
        }

        const d = new Date(value);
        return Number.isNaN(d.getTime()) ? null : d;
      };

      const now = new Date();
      const todayStart = startOfDay(now);
      const tomorrowStart = addDays(todayStart, 1);
      const monthStart = new Date(now.getFullYear(), now.getMonth(), 1, 0, 0, 0, 0);
      const nextMonthStart = new Date(now.getFullYear(), now.getMonth() + 1, 1, 0, 0, 0, 0);
      /* O MESMO PEDAÇO do mês anterior, e não ele inteiro: ver
         `janelaDoMesAnterior`. Comparar 16 dias com 31 dava -53% de mentira. */
      const janelaAnterior = janelaDoMesAnterior(now);

      const rawEntries = (flowData ?? []).map((entry) => ({
        ...entry,
        normalizedOrigin: normalizeFlowOrigin(entry.origin, entry.description),
      }));

      const pedidoPaymentIds = Array.from(
        new Set(
          rawEntries
            .filter((entry) => entry.normalizedOrigin === "PEDIDO" && typeof entry.reference_id === "string")
            .map((entry) => entry.reference_id as string)
        )
      );
      const paymentToOrder = new Map<string, string>();
      if (pedidoPaymentIds.length > 0) {
        const { data: paymentsWithOrder } = await supabase
          .from("payments")
          .select("id,order_id,user_id,payment_method")
          .in("id", pedidoPaymentIds)
          .in("user_id", tenantIds);
        (paymentsWithOrder ?? []).forEach((p) => {
          if (typeof p.id === "string" && typeof p.order_id === "string") {
            paymentToOrder.set(p.id, p.order_id);
          }
        });
      }

      const canceledOrderIds = new Set(
        (ordersData ?? [])
          .filter((order) => isCanceledOrderStatus(order.status))
          .map((order) => order.id)
          .filter((id): id is string => typeof id === "string")
      );

      const validInEntries = rawEntries.filter((entry) => {
        if (entry.type !== "IN") return false;
        if (entry.normalizedOrigin === "PEDIDO") {
          const ref = typeof entry.reference_id === "string" ? entry.reference_id : null;
          const orderId = ref ? paymentToOrder.get(ref) : null;
          if (orderId && canceledOrderIds.has(orderId)) return false;
        }
        return entry.normalizedOrigin === "PEDIDO" || entry.normalizedOrigin === "MANUAL" || entry.normalizedOrigin === "AJUSTE";
      });

      const totalReceivedToday = validInEntries
        .filter((entry) => {
          const dt = parsePaymentDate(entry.date);
          if (!dt) return false;
          return dt >= todayStart && dt < tomorrowStart;
        })
        .reduce((sum, entry) => sum + (Number(entry.amount) || 0), 0);

      const totalReceivedThisMonth = validInEntries
        .filter((entry) => {
          const dt = parsePaymentDate(entry.date);
          if (!dt) return false;
          return dt >= monthStart && dt < nextMonthStart;
        })
        .reduce((sum, entry) => sum + (Number(entry.amount) || 0), 0);

      /* A MESMA regra do mês atual, uma janela para trás. Comparar com um
         total calculado de outro jeito repetiria o erro do percentual. */
      const totalReceivedPrevMonth = validInEntries
        .filter((entry) => {
          const dt = parsePaymentDate(entry.date);
          if (!dt) return false;
          return dt >= janelaAnterior.inicio && dt < janelaAnterior.fim;
        })
        .reduce((sum, entry) => sum + (Number(entry.amount) || 0), 0);

      const activeOrders = ordersData.filter((order) => !isCanceledOrderStatus(order.status));

      const totalOpenAmount = activeOrders
        .filter((o) => o.financial_status !== "paid")
        .reduce((sum, o) => sum + (Number(o.total_amount) - (Number(o.paid_amount) || 0)), 0);

      const paidOrders = activeOrders.filter((o) => o.financial_status === "paid").length;
      const pendingOrders = activeOrders.filter((o) => o.financial_status !== "paid").length;

      // Estatísticas por método de pagamento
      const paymentMethodByPaymentId = new Map<string, string>();
      if (pedidoPaymentIds.length > 0) {
        const { data: paymentMethods } = await supabase
          .from("payments")
          .select("id,payment_method,user_id")
          .in("id", pedidoPaymentIds)
          .in("user_id", tenantIds);
        (paymentMethods ?? []).forEach((payment) => {
          if (typeof payment.id === "string") {
            paymentMethodByPaymentId.set(payment.id, payment.payment_method || "unknown");
          }
        });
      }

      const paymentMethodStats = validInEntries.reduce((acc, entry) => {
        const method =
          entry.normalizedOrigin === "MANUAL"
            ? "manual"
            : paymentMethodByPaymentId.get(String(entry.reference_id || "")) || "unknown";
        const existing = acc.find(m => m.method === method);
        const amount = Number(entry.amount) || 0;
        
        if (existing) {
          existing.count += 1;
          existing.amount += amount;
        } else {
          acc.push({ method, count: 1, amount });
        }
        
        return acc;
      }, [] as { method: string; count: number; amount: number }[]);

      const manualEntries = validInEntries.filter((entry) => entry.normalizedOrigin === "MANUAL");
      const orderEntries = validInEntries.filter((entry) => entry.normalizedOrigin === "PEDIDO");
      const manualInTotal = manualEntries.reduce((sum, entry) => sum + (Number(entry.amount) || 0), 0);
      const ordersInTotal = orderEntries.reduce((sum, entry) => sum + (Number(entry.amount) || 0), 0);

      setMetrics({
        totalReceivedToday,
        totalReceivedThisMonth,
        totalReceivedPrevMonth,
        totalOpenAmount,
        paidOrders,
        pendingOrders,
        paymentMethodStats: paymentMethodStats.sort((a, b) => b.amount - a.amount),
        manualInTotal,
        manualInCount: manualEntries.length,
        ordersInTotal,
        ordersInCount: orderEntries.length,
      });

    } catch (error) {
      console.error('Erro ao buscar métricas financeiras:', error);
    } finally {
      setLoading(false);
    }
  }

  if (loading) {
    return (
      <div className="space-y-6">
        <PageHeader
          title="Financeiro"
          subtitle="Visão geral das finanças da sua empresa"
        />
        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
          {[...Array(6)].map((_, i) => (
            <div key={i} className="ks-surface p-6 rounded-xl animate-pulse">
              <div className="h-8 bg-gray-200 rounded mb-4"></div>
              <div className="h-6 bg-gray-200 rounded"></div>
            </div>
          ))}
        </div>
      </div>
    );
  }

  const formatCurrency = (value: number) => {
    return new Intl.NumberFormat('pt-BR', {
      style: 'currency',
      currency: 'BRL'
    }).format(value);
  };

  /* O dinheiro desta tela passa pelo <Valor>: sem a permissao de ver
     valores, os numeros aparecem borrados e a tela continua utilizavel. */
  const dinheiro = (v: number) => <Valor>{formatCurrency(v)}</Valor>;

  /* A fatia e o todo saem da mesma lista: ver `lib/parte-do-total.ts`. */
  const totalDosMetodos = somaDasFatias(metrics?.paymentMethodStats);

  return (
    <div className="space-y-6">
      <PageHeader
        title="Financeiro"
        subtitle="Visão geral das finanças da sua empresa"
      />

      <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
        <StatCard
          title="Recebido Hoje"
          value={dinheiro(metrics?.totalReceivedToday || 0)}
          icon={DollarSign}
          description="Entradas do dia"
        />
        
        <StatCard
          title="Recebido no Mês"
          value={dinheiro(metrics?.totalReceivedThisMonth || 0)}
          icon={Calendar}
          /* Os dois eram fixos no código: "Janeiro 2026" e "+12%" em verde,
             para toda empresa, em todo mês. Ver `lib/parte-do-total.ts`. */
          description={nomeDoMes(new Date())}
          trend={variacaoDoMes(metrics?.totalReceivedThisMonth || 0, metrics?.totalReceivedPrevMonth || 0) ?? undefined}
        />
        
        <StatCard
          title="Em Aberto"
          value={dinheiro(metrics?.totalOpenAmount || 0)}
          icon={Package}
          description="A receber"
        />
        
        <StatCard
          title="Pedidos Pagos"
          value={metrics?.paidOrders.toString() || "0"}
          icon={Check}
          description="Total concluídos"
        />
        
        <StatCard
          title="Pedidos Pendentes"
          value={metrics?.pendingOrders.toString() || "0"}
          icon={Clock}
          description="Aguardando pagamento"
        />
        
        <StatCard
          title="Método Mais Usado"
          value={paymentMethodLabel(metrics?.paymentMethodStats[0]?.method || "")}
          icon={CreditCard}
          description={`${metrics?.paymentMethodStats[0]?.count || 0} transações`}
        />
      </div>

      {/* Resumo por Método de Pagamento */}
      <div className="ks-surface p-6 rounded-xl">
        <h3 className="text-lg font-semibold text-[var(--ks-color-text-primary)]">
          Métodos de Pagamento
        </h3>
        {/* Os cartões de cima falam do MÊS; este bloco fala de TODO o histórico.
            Sem dizer isso, a pessoa lê os dois como a mesma janela — e foi
            exatamente essa confusão que escondeu a divisão errada de antes. */}
        <p className="text-xs text-[var(--ks-color-text-muted)] mb-4">Desde o primeiro lançamento</p>
        <div className="grid grid-cols-1 md:grid-cols-2 gap-3 mb-4">
          <div className="p-3 rounded-xl bg-[var(--ks-color-bg-subtle)] border border-[var(--ks-color-border-subtle)]">
            <p className="text-xs text-[var(--ks-color-text-soft)]">Entradas de pedidos</p>
            <p className="text-sm font-semibold text-[var(--ks-color-text-primary)]">{dinheiro(metrics?.ordersInTotal || 0)}</p>
            <p className="text-xs text-[var(--ks-color-text-muted)]">{metrics?.ordersInCount || 0} lançamentos</p>
          </div>
          <div className="p-3 rounded-xl bg-[var(--ks-color-bg-subtle)] border border-[var(--ks-color-border-subtle)]">
            <p className="text-xs text-[var(--ks-color-text-soft)]">Lançamentos manuais</p>
            <p className="text-sm font-semibold text-[var(--ks-color-text-primary)]">{dinheiro(metrics?.manualInTotal || 0)}</p>
            <p className="text-xs text-[var(--ks-color-text-muted)]">{metrics?.manualInCount || 0} lançamentos</p>
          </div>
        </div>
        
        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
          {metrics?.paymentMethodStats.map((stat, index) => (
            <div key={index} className="p-4 bg-[var(--ks-color-bg-subtle)] rounded-lg">
              <div className="flex items-center justify-between mb-2">
                <span className="text-sm font-medium text-[var(--ks-color-text-primary)]">
                  {paymentMethodLabel(stat.method)}
                </span>
                <span className="text-xs text-[var(--ks-color-text-muted)]">
                  {stat.count} transações
                </span>
              </div>
              
              <div className="text-lg font-bold text-[var(--ks-color-text-primary)]">
                {dinheiro(stat.amount)}
              </div>
              
              <div className="text-xs text-[var(--ks-color-text-soft)]">
                {parteDoTotal(stat.amount, totalDosMetodos)} do total
              </div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}
