"use client";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { usePermissoes } from "@/lib/permissoes-do-usuario";
import { DollarSign, Calendar, FileText, AlertCircle, Clock, CheckCircle2, TrendingUp, Wallet, X, Edit2, Plus, Undo2 } from "lucide-react";
import { getSupabaseClient } from "@/lib/supabase";
import { getCompanyContext } from "@/lib/company-context";
import { deletePayment, registerPayment } from "@/app/actions/financial";
import { resolveLogoSrc, resolveBankDisplayName } from "@/lib/bank-logos";
import { PageHeader } from "@/components/ui/page-header";
import { Input } from "@/components/ui/input";
import { CustomSelect } from "@/components/ui/custom-select";
import { CustomDatePicker } from "@/components/ui/custom-date-picker";
import { filterAccountsByLiquidationMethod, normalizeLiquidationMethod } from "@/lib/liquidation-accounts";
import { cronograma, normalizarCondicoes, proximaParcelaEmAberto, situacaoDasParcelas } from "@/lib/condicoes-comerciais";
import { Valor } from "@/components/ui/valor";

interface ReceivableAccount {
  id: string;
  account_code: string;
  title_status: "PENDING" | "PARTIALLY_PAID" | "PAID" | "OVERDUE" | "CANCELED";
  client_name: string;
  client_company?: string;
  total_amount: number;
  paid_amount: number;
  balance: number;
  financial_status: "unpaid" | "partially_paid" | "paid";
  created_at: string;
  /* Pedido com condições combinadas na proposta vence na próxima parcela em
     aberto; sem condições, repete a data de criação. O campo nao aparece na
     linha — serve so para ordenar e filtrar. */
  due_date: string;
  /* "receivable" e o titulo avulso, que tem baixa propria. "order" e o saldo
     em aberto de um pedido, que se liquida pelo proprio pedido. */
  source: "receivable" | "order";
  /* Venda de PDV nao estorna pagamento a pagamento: a rotina do PDV cancela a
     venda inteira e reverte tudo junto. Sem esta marca a tela ofereceria uma
     acao que o banco recusa. */
  ehPdv?: boolean;
  bank_account_id?: string | null;
}

type OrderRow = {
  id: string;
  number: number | string | null;
  status: string | null;
  total_amount: number | null;
  paid_amount: number | null;
  financial_status: "unpaid" | "partially_paid" | "paid" | null;
  created_at: string;
  delivery_date?: string | null;
  payment_terms?: unknown;
  clients: { id: string; name: string | null; company_name: string | null }
    | Array<{ id: string; name: string | null; company_name: string | null }>
    | null;
  internal_notes?: string | null;
  quotes?: { title?: string | null; internal_notes?: string | null }
    | Array<{ title?: string | null; internal_notes?: string | null }>
    | null;
};

/* Mesma leitura que /api/pdv/cancel-sale faz para reconhecer uma venda de
   balcao: nao existe coluna dizendo isso, so a marca deixada no orcamento. */
function ehVendaDePdv(pedido: OrderRow) {
  const t = String(primeiroOuNulo(pedido.quotes)?.title || "").toLowerCase();
  const qn = String(primeiroOuNulo(pedido.quotes)?.internal_notes || "").toLowerCase();
  const n = String(pedido.internal_notes || "").toLowerCase();
  return t.includes("venda pdv") || qn.includes("origem:pdv") || n.includes("pdv");
}

function primeiroOuNulo<T>(valor: T | T[] | null | undefined): T | null {
  if (Array.isArray(valor)) return valor[0] ?? null;
  return valor ?? null;
}

function pedidoCancelado(status: string | null | undefined) {
  const s = String(status || "").trim().toLowerCase();
  return s === "canceled" || s === "cancelled";
}

/** Uma baixa ja registrada, seja de titulo avulso ou de pedido. */
type LancamentoRecebido = {
  id: string;
  amount: number;
  data: string;
  forma: string | null;
};

function rotuloDaForma(forma: string | null) {
  const achado = paymentMethodOptions.find((o) => o.value === forma);
  return achado?.label ?? "Não informada";
}

function formatarData(valor: string) {
  const d = new Date(valor.length <= 10 ? `${valor}T12:00:00` : valor);
  return Number.isNaN(d.getTime()) ? valor : d.toLocaleDateString("pt-BR");
}

type ManualReceivableRow = {
  id: string;
  description: string;
  client_name: string | null;
  client_company: string | null;
  total_amount: number;
  paid_amount: number;
  due_date: string;
  status: "PENDING" | "PARTIALLY_PAID" | "PAID" | "OVERDUE" | "CANCELED";
  created_at: string;
  bank_account_id: string | null;
};

type BankAccountOption = {
  bank_account_id: string;
  name: string | null;
  bank_name: string | null;
  bank_code?: string | null;
  logo_key?: string | null;
  active?: boolean | null;
  type?: string | null;
};
type ClientOption = { id: string; name: string; company_name: string | null };

const paymentMethodOptions = [
  { value: "transfer", label: "Transferência" },
  { value: "pix", label: "Pix" },
  { value: "credit_card", label: "Cartão de Crédito" },
  { value: "debit_card", label: "Cartão de Débito" },
  { value: "cash", label: "Dinheiro" },
];

function statusLabel(status: string) {
  switch (status) {
    case 'unpaid': return 'Aberto';
    case 'partially_paid': return 'Parcial';
    case 'paid': return 'Pago';
    default: return status;
  }
}

function statusClass(status: string) {
  switch (status) {
    case 'unpaid': return 'ks-chip ks-chip-danger';
    case 'partially_paid': return 'ks-chip ks-chip-warning';
    case 'paid': return 'ks-chip ks-chip-success';
    default: return 'ks-chip';
  }
}

function formatMoney(value: number) {
  return new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" }).format(value || 0);
}

/* 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>;

function maskCurrencyInput(raw: string) {
  const digits = raw.replace(/\D/g, "");
  if (!digits) return "";
  const numeric = Number(digits) / 100;
  return numeric.toLocaleString("pt-BR", { style: "currency", currency: "BRL" });
}

function parseCurrencyInput(masked: string) {
  const normalized = masked.replace(/\s/g, "").replace("R$", "").replace(/\./g, "").replace(",", ".");
  const value = Number(normalized);
  return Number.isFinite(value) ? value : NaN;
}

type PeriodFilterType = 'all' | 'today' | 'week' | 'month' | 'custom';

function getPeriodDates(type: PeriodFilterType, start?: string, end?: string): { startDate: Date | null, endDate: Date | null } {
  const now = new Date();
  
  if (type === 'today') {
    const startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate());
    const endDate = new Date(startDate.getTime() + 24 * 60 * 60 * 1000);
    return { startDate, endDate };
  }
  
  if (type === 'week') {
    const day = now.getDay();
    const diff = now.getDate() - day + (day === 0 ? -6 : 1);
    const startDate = new Date(now.getFullYear(), now.getMonth(), diff);
    const endDate = new Date(startDate.getTime() + 7 * 24 * 60 * 60 * 1000);
    return { startDate, endDate };
  }
  
  if (type === 'month') {
    const startDate = new Date(now.getFullYear(), now.getMonth(), 1);
    const endDate = new Date(now.getFullYear(), now.getMonth() + 1, 1);
    return { startDate, endDate };
  }
  
  if (type === 'custom' && start && end) {
    const startDate = new Date(`${start}T00:00:00`);
    const endDate = new Date(`${end}T23:59:59`);
    return { startDate, endDate };
  }
  
  return { startDate: null, endDate: null };
}

export default function ReceivablesPage() {
  const { pode } = usePermissoes();
  /* Ler o financeiro e ver os numeros; lancar e baixar e outra coisa. */
  /* Criar titulo e dar baixa nele sao permissoes diferentes: o vendedor
     costuma poder conferir e registrar o recebimento sem poder lancar. */
  const podeLancar = pode("financial.receivables.write");

  const [receivables, setReceivables] = useState<ReceivableAccount[]>([]);
  const hasLoadedReceivablesRef = useRef(false);
  const [loading, setLoading] = useState(true);
  const [isRefetching, setIsRefetching] = useState(false);
  const [searchTerm, setSearchTerm] = useState('');
  const [activeFilter, setActiveFilter] = useState<'all' | 'unpaid' | 'partially_paid' | 'paid'>('all');
  
  const [periodType, setPeriodType] = useState<PeriodFilterType>('month');
  const [customStart, setCustomStart] = useState(() => {
    const now = new Date();
    const firstDay = new Date(now.getFullYear(), now.getMonth(), 1);
    return `${firstDay.getFullYear()}-${String(firstDay.getMonth() + 1).padStart(2, '0')}-01`;
  });
  const [customEnd, setCustomEnd] = useState(() => {
    const now = new Date();
    return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
  });
  
  const [showCustomDateUI, setShowCustomDateUI] = useState(false);
  const [showCreateModal, setShowCreateModal] = useState(false);
  const [creating, setCreating] = useState(false);
  const [receiving, setReceiving] = useState(false);
  const [showReceiveModal, setShowReceiveModal] = useState(false);
  const [receiveError, setReceiveError] = useState("");
  const [receiveTarget, setReceiveTarget] = useState<ReceivableAccount | null>(null);
  const [receiveForm, setReceiveForm] = useState({
    amount: "",
    received_at: new Date().toISOString().slice(0, 10),
    bank_account_id: "",
    payment_method: "transfer",
  });
  /* Estorno: a linha guarda o que ja foi recebido, e cada lancamento pode ser
     desfeito um a um. Um titulo pode ter varias baixas parciais, entao nao da
     para "estornar a linha" — e preciso escolher qual. */
  const [showEstornoModal, setShowEstornoModal] = useState(false);
  const [estornoTarget, setEstornoTarget] = useState<ReceivableAccount | null>(null);
  const [estornoLista, setEstornoLista] = useState<LancamentoRecebido[]>([]);
  const [estornoCarregando, setEstornoCarregando] = useState(false);
  const [estornandoId, setEstornandoId] = useState<string | null>(null);
  const [estornoError, setEstornoError] = useState("");

  const [bankAccounts, setBankAccounts] = useState<BankAccountOption[]>([]);
  const [clients, setClients] = useState<ClientOption[]>([]);
  const [newAccount, setNewAccount] = useState({
    description: "",
    client_id: "",
    client_name: "",
    client_company: "",
    total_amount: "",
    due_date: new Date().toISOString().slice(0, 10),
    bank_account_id: "",
  });
  
  // Ref para disparar a busca apenas quando o usuário clica em "Aplicar"
  const [appliedCustomDates, setAppliedCustomDates] = useState({ start: customStart, end: customEnd });
  useEffect(() => {
    loadBankAccounts();
    loadClients();
  }, []);

  async function loadBankAccounts() {
    try {
      const response = await fetch("/api/bank-accounts", { cache: "no-store" });
      const payload = (await response.json().catch(() => ({}))) as { accounts?: BankAccountOption[]; error?: string };
      if (!response.ok) {
        setBankAccounts([]);
        return;
      }
      const rows = (payload.accounts ?? []).filter((row) => row.bank_account_id);
      setBankAccounts(rows);
    } catch {
      setBankAccounts([]);
    }
  }

  async function loadClients() {
    try {
      const supabase = getSupabaseClient();
      const {
        data: { user },
      } = await supabase.auth.getUser();
      if (!user) return;
      const ctx = await getCompanyContext(supabase, user);
      const tenantIds = ctx.tenantIds?.length ? ctx.tenantIds : [user.id];
      const { data } = await supabase
        .from("clients")
        .select("id,name,company_name")
        .in("user_id", tenantIds)
        .order("name", { ascending: true });
      setClients((data ?? []) as ClientOption[]);
    } catch {
      setClients([]);
    }
  }

  const fetchReceivables = useCallback(async () => {
    if (hasLoadedReceivablesRef.current) setIsRefetching(true);
    else setLoading(true);
    try {
      const { startDate, endDate } = getPeriodDates(periodType, appliedCustomDates.start, appliedCustomDates.end);
      let manualRows: ManualReceivableRow[] = [];
      const params = new URLSearchParams();
      if (startDate) params.set("start", startDate.toISOString().slice(0, 10));
      if (endDate) params.set("end", endDate.toISOString().slice(0, 10));

      /* Quando o periodo alcanca hoje, os titulos em aberto que venceram antes
         dele vem junto: sao os mais urgentes da carteira, e some-los sob o
         filtro de "Este mes" era o que fazia a tela parecer vazia. Um periodo
         fechado no passado nao recebe esse acrescimo — quem escolheu um mes
         especifico quer aquele mes. */
      const alcancaHoje = !endDate || endDate.getTime() >= Date.now();
      if (startDate && alcancaHoje) params.set("vencidas", "1");
      const manualResp = await fetch(`/api/accounts-receivable?${params.toString()}`, { cache: "no-store" });
      if (manualResp.ok) {
        const payload = (await manualResp.json()) as { accounts?: ManualReceivableRow[] };
        manualRows = payload.accounts ?? [];
      }
      const manualReceivables: ReceivableAccount[] = manualRows
        .filter((item) => item.status !== "CANCELED")
        .map((item) => ({
          id: item.id,
          account_code: `R${item.id.slice(-4).toUpperCase()}`,
          title_status: item.status,
          client_name: item.client_name?.trim() || item.description,
          client_company: item.client_company ?? undefined,
          total_amount: Number(item.total_amount ?? 0),
          paid_amount: Number(item.paid_amount ?? 0),
          balance: Math.max(0, Number(item.total_amount ?? 0) - Number(item.paid_amount ?? 0)),
          financial_status:
            item.status === "PAID" ? "paid" : item.status === "PARTIALLY_PAID" ? "partially_paid" : "unpaid",
          created_at: item.created_at,
          due_date: item.due_date,
          source: "receivable",
          bank_account_id: item.bank_account_id,
        }));

      /* Boa parte do que a empresa tem a receber nao esta em titulo avulso:
         esta em pedido entregue e ainda nao pago. Esta tela listava os dois e
         perdeu os pedidos numa refatoracao — quem so vendia por pedido passou a
         ver a carteira vazia.

         Vale a mesma regra dos titulos: pedido com saldo em aberto nao some por
         causa do filtro de periodo enquanto o periodo alcancar hoje. Divida em
         aberto e divida em aberto, tenha ela tres dias ou seis meses. */
      const supabase = getSupabaseClient();
      const {
        data: { user },
      } = await supabase.auth.getUser();

      let pedidos: ReceivableAccount[] = [];
      if (user) {
        const ctx = await getCompanyContext(supabase, user);
        const tenantIds = ctx.tenantIds?.length ? ctx.tenantIds : [user.id];

        const colunas =
          "id,number,status,total_amount,paid_amount,financial_status,created_at,delivery_date,payment_terms,internal_notes,clients (id, name, company_name),quotes (title, internal_notes)";
        const { data: dentroDoPeriodo } = await (() => {
          let q = supabase.from("orders").select(colunas).in("user_id", tenantIds);
          if (startDate) q = q.gte("created_at", startDate.toISOString());
          if (endDate) q = q.lt("created_at", endDate.toISOString());
          return q.order("created_at", { ascending: false });
        })();

        /* Os que ficaram para tras do periodo, mas ainda devem. */
        let emAberto: unknown[] = [];
        if (startDate && alcancaHoje) {
          const { data } = await supabase
            .from("orders")
            .select(colunas)
            .in("user_id", tenantIds)
            .lt("created_at", startDate.toISOString())
            .neq("financial_status", "paid")
            .order("created_at", { ascending: false });
          emAberto = data ?? [];
        }

        const vistos = new Set<string>();
        pedidos = [...((dentroDoPeriodo ?? []) as unknown[]), ...emAberto]
          .map((linha) => linha as unknown as OrderRow)
          .filter((pedido) => {
            if (pedidoCancelado(pedido.status)) return false;
            if (vistos.has(pedido.id)) return false;
            vistos.add(pedido.id);
            return true;
          })
          .map((pedido) => {
            const total = Number(pedido.total_amount ?? 0);
            const pago = Number(pedido.paid_amount ?? 0);
            const cliente = primeiroOuNulo(pedido.clients);
            const situacao = pedido.financial_status ?? "unpaid";
            /* Com condições combinadas, o vencimento é o da próxima parcela em
               aberto (o dinheiro recebido quita as parcelas na ordem). */
            const condicoes = normalizarCondicoes(pedido.payment_terms);
            const proximaParcela = condicoes
              ? proximaParcelaEmAberto(
                  situacaoDasParcelas(
                    cronograma(condicoes, total, { aprovacao: pedido.created_at, entrega: pedido.delivery_date ?? null }),
                    pago
                  )
                )
              : null;
            return {
              id: pedido.id,
              account_code: pedido.number ? `#${pedido.number}` : `P${pedido.id.slice(-4).toUpperCase()}`,
              title_status:
                situacao === "paid" ? "PAID" : situacao === "partially_paid" ? "PARTIALLY_PAID" : "PENDING",
              client_name: cliente?.name || "Cliente não informado",
              client_company: cliente?.company_name ?? undefined,
              total_amount: total,
              paid_amount: pago,
              balance: Math.max(0, total - pago),
              financial_status: situacao,
              created_at: pedido.created_at,
              due_date: proximaParcela?.vencimento ?? pedido.created_at.slice(0, 10),
              source: "order" as const,
              ehPdv: ehVendaDePdv(pedido),
              bank_account_id: null,
            } satisfies ReceivableAccount;
          })
          /* Fora do periodo so entra quem ainda deve; dentro do periodo entra
             tudo, senao os cards de "totalmente pagos" ficariam sem base. */
          .filter((pedido) => {
            const dentro =
              (!startDate || new Date(pedido.created_at) >= startDate) &&
              (!endDate || new Date(pedido.created_at) < endDate);
            return dentro || pedido.balance > 0.01;
          });
      }

      setReceivables(
        [...manualReceivables, ...pedidos].sort(
          (a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
        )
      );

    } catch (error) {
      console.error('Erro ao buscar contas a receber:', error);
    } finally {
      hasLoadedReceivablesRef.current = true;
      setLoading(false);
      setIsRefetching(false);
    }
  }, [appliedCustomDates, periodType]);

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

  const activeBankAccounts = useMemo(
    () => bankAccounts.filter((account) => account.active !== false),
    [bankAccounts]
  );
  const receiveCompatibleAccounts = useMemo(
    () => filterAccountsByLiquidationMethod(activeBankAccounts, normalizeLiquidationMethod(receiveForm.payment_method)),
    [activeBankAccounts, receiveForm.payment_method]
  );
  const receiveAccountLabel = receiveForm.payment_method === "cash" ? "Caixa físico de entrada *" : "Conta bancária de entrada *";

  async function handleCreateManualReceivable() {
    const amountValue = parseCurrencyInput(newAccount.total_amount);
    if (!newAccount.description.trim()) return alert("Informe a descrição.");
    if (!newAccount.total_amount || !Number.isFinite(amountValue) || amountValue <= 0) return alert("Informe um valor válido.");
    if (!newAccount.due_date) return alert("Informe a data de vencimento.");
    if (!newAccount.bank_account_id) return alert("Selecione a conta bancária.");

    setCreating(true);
    try {
      const resp = await fetch("/api/accounts-receivable", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          description: newAccount.description,
          client_name: newAccount.client_name || null,
          client_company: newAccount.client_company || null,
          total_amount: amountValue,
          due_date: newAccount.due_date,
          bank_account_id: newAccount.bank_account_id,
        }),
      });
      if (!resp.ok) {
        const payload = (await resp.json().catch(() => ({}))) as { error?: string };
        alert(payload.error || "Falha ao criar conta a receber.");
        return;
      }
      setShowCreateModal(false);
      setNewAccount({
        description: "",
        client_id: "",
        client_name: "",
        client_company: "",
        total_amount: "",
        due_date: new Date().toISOString().slice(0, 10),
        bank_account_id: "",
      });
      await fetchReceivables();
    } finally {
      setCreating(false);
    }
  }

  async function handleReceiveManual(account: ReceivableAccount) {
    if (!account.id) return;
    setReceiveError("");
    setReceiveTarget(account);
    setReceiveForm({
      amount: maskCurrencyInput(String(Math.round((account.balance > 0 ? account.balance : 0) * 100))),
      received_at: new Date().toISOString().slice(0, 10),
      bank_account_id: account.bank_account_id ?? "",
      payment_method: "transfer",
    });
    setShowReceiveModal(true);
  }

  /* Abre a lista de baixas ja feitas nesta linha, para escolher qual desfazer.
     Titulo avulso guarda em `receivable_receipts`, pedido em `payments` — a
     leitura muda, o que a tela mostra e a mesma coisa. */
  async function abrirEstorno(account: ReceivableAccount) {
    setEstornoTarget(account);
    setEstornoError("");
    setEstornoLista([]);
    setShowEstornoModal(true);
    setEstornoCarregando(true);
    try {
      const supabase = getSupabaseClient();
      if (account.source === "order") {
        const { data, error } = await supabase
          .from("payments")
          .select("id,amount,payment_date,payment_method")
          .eq("order_id", account.id)
          .order("payment_date", { ascending: false });
        if (error) throw error;
        setEstornoLista(
          (data ?? []).map((p) => ({
            id: String(p.id),
            amount: Number(p.amount ?? 0),
            data: String(p.payment_date ?? ""),
            forma: (p.payment_method as string | null) ?? null,
          }))
        );
      } else {
        const { data, error } = await supabase
          .from("receivable_receipts")
          .select("id,amount,received_at,payment_method,reversed_at")
          .eq("receivable_id", account.id)
          .is("reversed_at", null)
          .order("received_at", { ascending: false });
        if (error) throw error;
        setEstornoLista(
          (data ?? []).map((r) => ({
            id: String(r.id),
            amount: Number(r.amount ?? 0),
            data: String(r.received_at ?? ""),
            forma: (r.payment_method as string | null) ?? null,
          }))
        );
      }
    } catch (erro) {
      setEstornoError(erro instanceof Error ? erro.message : "Falha ao carregar os recebimentos.");
    } finally {
      setEstornoCarregando(false);
    }
  }

  /* Venda de PDV nao se desfaz pagamento a pagamento: a rotina do balcao
     reverte tudo e cancela a venda no mesmo passo, porque uma venda de balcao
     meio estornada nao e um estado que exista na loja. */
  async function cancelarVendaPdv() {
    if (!estornoTarget) return;
    setEstornandoId("pdv");
    setEstornoError("");
    try {
      const resp = await fetch("/api/pdv/cancel-sale", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ order_id: estornoTarget.id }),
      });
      const payload = (await resp.json().catch(() => ({}))) as { error?: string };
      if (!resp.ok) {
        setEstornoError(payload.error || "Falha ao cancelar a venda do PDV.");
        return;
      }
      setShowEstornoModal(false);
      setEstornoTarget(null);
      await fetchReceivables();
    } finally {
      setEstornandoId(null);
    }
  }

  /* Depois de estornar tudo, o pedido continua na carteira devendo o valor
     cheio. Se a venda nao vai mesmo acontecer, cancelar e o que tira ele da
     lista — e a rota so aceita cancelar quando nao ha mais pagamento. */
  async function cancelarPedido() {
    if (!estornoTarget) return;
    setEstornandoId("cancelar");
    setEstornoError("");
    try {
      const resp = await fetch("/api/orders/status", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ id: estornoTarget.id, status: "canceled" }),
      });
      const payload = (await resp.json().catch(() => ({}))) as { error?: string };
      if (!resp.ok) {
        setEstornoError(payload.error || "Falha ao cancelar o pedido.");
        return;
      }
      setShowEstornoModal(false);
      setEstornoTarget(null);
      await fetchReceivables();
    } finally {
      setEstornandoId(null);
    }
  }

  async function estornarLancamento(lancamento: LancamentoRecebido) {
    if (!estornoTarget) return;
    setEstornandoId(lancamento.id);
    setEstornoError("");
    try {
      if (estornoTarget.source === "order") {
        const resultado = await deletePayment(lancamento.id, estornoTarget.id);
        if (resultado?.error) {
          setEstornoError(resultado.error);
          return;
        }
      } else {
        /* A rotina do banco marca o recebimento como revertido, lanca o
           contra-lancamento no caixa e recalcula o status do titulo. Ela ja
           confere permissao e empresa por conta propria. */
        const supabase = getSupabaseClient();
        const { error } = await supabase.rpc("reverse_receipt_with_cash_flow", {
          p_receipt_id: lancamento.id,
          p_reason: "Estorno pela tela de contas a receber",
        });
        if (error) {
          setEstornoError(error.message || "Falha ao estornar o recebimento.");
          return;
        }
      }

      setEstornoLista((atual) => atual.filter((l) => l.id !== lancamento.id));
      await fetchReceivables();
    } finally {
      setEstornandoId(null);
    }
  }

  async function submitReceiveManual() {
    if (!receiveTarget?.id) return;
    const amount = parseCurrencyInput(receiveForm.amount);
    if (!Number.isFinite(amount) || amount <= 0) {
      setReceiveError("Informe um valor de recebimento válido.");
      return;
    }
    if (!receiveForm.bank_account_id) {
      setReceiveError("Selecione a conta bancária para receber.");
      return;
    }

    setReceiving(true);
    setReceiveError("");
    try {
      /* Titulo avulso e pedido guardam o recebimento em lugares diferentes: um
         em `receivable_receipts`, outro em `payments`, cada um com sua rotina
         de caixa. O modal e o mesmo porque a pergunta ao usuario e a mesma —
         quanto, quando, como e em que conta. Muda so para onde vai. */
      if (receiveTarget.source === "order") {
        const dados = new FormData();
        dados.set("orderId", receiveTarget.id);
        dados.set("amount", String(amount));
        dados.set("paymentMethod", receiveForm.payment_method);
        dados.set("paymentDate", receiveForm.received_at);
        dados.set("tzOffsetMinutes", String(new Date().getTimezoneOffset()));
        dados.set("bankAccountId", receiveForm.bank_account_id);
        dados.set("notes", "");

        const resultado = await registerPayment(dados);
        if (resultado?.error) {
          setReceiveError(resultado.error);
          return;
        }
      } else {
        const resp = await fetch(`/api/accounts-receivable/${receiveTarget.id}/receive`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            amount,
            received_at: receiveForm.received_at,
            bank_account_id: receiveForm.bank_account_id,
            payment_method: receiveForm.payment_method,
          }),
        });
        if (!resp.ok) {
          const payload = (await resp.json().catch(() => ({}))) as { error?: string };
          setReceiveError(payload.error || "Falha ao baixar recebimento.");
          return;
        }
      }

      setShowReceiveModal(false);
      setReceiveTarget(null);
      await fetchReceivables();
    } finally {
      setReceiving(false);
    }
  }

  const filteredReceivables = receivables.filter(account => {
    const matchesSearch = account.client_name.toLowerCase().includes(searchTerm.toLowerCase()) ||
      account.client_company?.toLowerCase().includes(searchTerm.toLowerCase()) ||
      account.account_code.toString().includes(searchTerm);
      
    if (!matchesSearch) return false;
    
    if (activeFilter === 'unpaid') return account.financial_status === 'unpaid';
    if (activeFilter === 'partially_paid') return account.financial_status === 'partially_paid';
    if (activeFilter === 'paid') return account.financial_status === 'paid';
    return true;
  });

  // KPIs Metrics
  const totalFaturado = receivables.reduce((sum, acc) => sum + acc.total_amount, 0);
  const totalRecebido = receivables.reduce((sum, acc) => sum + acc.paid_amount, 0);
  const totalEmAberto = receivables.filter(a => a.financial_status === 'unpaid').reduce((sum, acc) => sum + acc.balance, 0);
  const totalParcial = receivables.filter(a => a.financial_status === 'partially_paid').reduce((sum, acc) => sum + acc.balance, 0);
  const saudePercent = totalFaturado > 0 ? (totalRecebido / totalFaturado) * 100 : 0;

  const countEmAberto = receivables.filter(a => a.financial_status === 'unpaid').length;
  const countParcial = receivables.filter(a => a.financial_status === 'partially_paid').length;
  const countPagos = receivables.filter(a => a.financial_status === 'paid').length;

  if (loading) {
    return (
      <div className="space-y-6">
        <PageHeader
          title="Contas a Receber"
          subtitle="Acompanhe a carteira oficial de títulos a receber"
        />
        
        <div className="ks-surface p-6 rounded-xl">
          <div className="animate-pulse space-y-4">
            <div className="h-8 bg-gray-200 rounded"></div>
            <div className="h-8 bg-gray-200 rounded"></div>
            <div className="h-8 bg-gray-200 rounded"></div>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className={`space-y-6 transition-opacity duration-200 ${isRefetching ? 'opacity-50 pointer-events-none' : 'opacity-100'}`}>
      <PageHeader
        title="Contas a Receber"
        subtitle="Acompanhe a carteira oficial de títulos a receber"
      />

      {/* KPIs Interativos (Scroll Horizontal no Mobile, Grid no Desktop) */}
      <div className="flex lg:grid lg:grid-cols-5 gap-4 sm:gap-6 w-full overflow-x-auto lg:overflow-visible pb-4 lg:pb-0 snap-x snap-mandatory hide-scrollbar">
        <div 
          onClick={() => setActiveFilter('all')}
          className={`ks-surface p-4 sm:p-5 rounded-xl cursor-pointer transition-all border-2 group shrink-0 w-[260px] lg:w-auto snap-start ${activeFilter === 'all' ? 'border-[var(--ks-color-primary)] ring-4 ring-[var(--ks-color-primary-light)]' : 'border-[var(--ks-color-border-subtle)] hover:border-gray-300'}`}
        >
          <div className="flex items-center gap-3 mb-3">
            <div className={`w-8 h-8 rounded-lg flex items-center justify-center shrink-0 ${activeFilter === 'all' ? 'bg-[var(--ks-color-primary)] text-white' : 'bg-[var(--ks-color-bg-subtle)] text-[var(--ks-color-text-muted)] group-hover:text-[var(--ks-color-primary)]'}`}>
              <Wallet size={16} />
            </div>
            <h3 className="text-xs sm:text-sm font-bold uppercase tracking-wider text-[var(--ks-color-text-muted)] group-hover:text-[var(--ks-color-text-primary)] transition-colors">Visão Geral</h3>
          </div>
          <p className="text-xl sm:text-2xl font-black text-[var(--ks-color-text-primary)]">
            {dinheiro(totalFaturado)}
          </p>
          <p className="text-xs text-[var(--ks-color-text-muted)] mt-1 font-medium">{receivables.length} pedidos no total</p>
        </div>

        <div 
          onClick={() => setActiveFilter('unpaid')}
          className={`ks-surface p-4 sm:p-5 rounded-xl cursor-pointer transition-all border-2 group shrink-0 w-[260px] lg:w-auto snap-start ${activeFilter === 'unpaid' ? 'border-rose-500 ring-4 ring-rose-100' : 'border-[var(--ks-color-border-subtle)] hover:border-gray-300'}`}
        >
          <div className="flex items-center gap-3 mb-3">
            <div className={`w-8 h-8 rounded-lg flex items-center justify-center shrink-0 ${activeFilter === 'unpaid' ? 'bg-rose-500 text-white' : 'bg-rose-50 text-rose-500 group-hover:bg-rose-100'}`}>
              <AlertCircle size={16} />
            </div>
            <h3 className="text-xs sm:text-sm font-bold uppercase tracking-wider text-[var(--ks-color-text-muted)] group-hover:text-rose-700 transition-colors">Aguardando Pagto.</h3>
          </div>
          <p className="text-xl sm:text-2xl font-black text-rose-600">
            {dinheiro(totalEmAberto)}
          </p>
          <p className="text-xs text-[var(--ks-color-text-muted)] mt-1 font-medium">{countEmAberto} pedidos pendentes</p>
        </div>

        <div 
          onClick={() => setActiveFilter('partially_paid')}
          className={`ks-surface p-4 sm:p-5 rounded-xl cursor-pointer transition-all border-2 group shrink-0 w-[260px] lg:w-auto snap-start ${activeFilter === 'partially_paid' ? 'border-amber-500 ring-4 ring-amber-100' : 'border-[var(--ks-color-border-subtle)] hover:border-gray-300'}`}
        >
          <div className="flex items-center gap-3 mb-3">
            <div className={`w-8 h-8 rounded-lg flex items-center justify-center shrink-0 ${activeFilter === 'partially_paid' ? 'bg-amber-500 text-white' : 'bg-amber-50 text-amber-600 group-hover:bg-amber-100'}`}>
              <Clock size={16} />
            </div>
            <h3 className="text-xs sm:text-sm font-bold uppercase tracking-wider text-[var(--ks-color-text-muted)] group-hover:text-amber-700 transition-colors">Recebimento Parcial</h3>
          </div>
          <p className="text-xl sm:text-2xl font-black text-amber-600">
            {dinheiro(totalParcial)}
          </p>
          <p className="text-xs text-[var(--ks-color-text-muted)] mt-1 font-medium">{countParcial} pedidos em andamento</p>
        </div>

        <div 
          onClick={() => setActiveFilter('paid')}
          className={`ks-surface p-4 sm:p-5 rounded-xl cursor-pointer transition-all border-2 group shrink-0 w-[260px] lg:w-auto snap-start ${activeFilter === 'paid' ? 'border-emerald-500 ring-4 ring-emerald-100' : 'border-[var(--ks-color-border-subtle)] hover:border-gray-300'}`}
        >
          <div className="flex items-center gap-3 mb-3">
            <div className={`w-8 h-8 rounded-lg flex items-center justify-center shrink-0 ${activeFilter === 'paid' ? 'bg-emerald-500 text-white' : 'bg-emerald-50 text-emerald-600 group-hover:bg-emerald-100'}`}>
              <CheckCircle2 size={16} />
            </div>
            <h3 className="text-xs sm:text-sm font-bold uppercase tracking-wider text-[var(--ks-color-text-muted)] group-hover:text-emerald-700 transition-colors">Totalmente Pagos</h3>
          </div>
          <p className="text-xl sm:text-2xl font-black text-emerald-600">
            {dinheiro(totalRecebido)}
          </p>
          <p className="text-xs text-[var(--ks-color-text-muted)] mt-1 font-medium">{countPagos} pedidos concluídos</p>
        </div>

        {/* Filtro de Período (5º Elemento) */}
        <div className="ks-surface p-4 sm:p-5 rounded-xl border-2 border-[var(--ks-color-border-subtle)] flex flex-col justify-between group relative shrink-0 w-[260px] lg:w-auto snap-start self-stretch">
          <div className="flex items-center gap-3 mb-3">
            <div className="w-8 h-8 rounded-lg flex items-center justify-center shrink-0 bg-[var(--ks-color-bg-subtle)] text-[var(--ks-color-text-muted)] group-hover:text-[var(--ks-color-primary)]">
              <Calendar size={16} />
            </div>
            <h3 className="text-xs sm:text-sm font-bold uppercase tracking-wider text-[var(--ks-color-text-muted)] group-hover:text-[var(--ks-color-text-primary)] transition-colors">Período</h3>
          </div>
          
          <div className="flex flex-col gap-2 flex-1 justify-end">
            <CustomSelect 
              value={periodType}
              onChange={(val) => {
                setPeriodType(val as PeriodFilterType);
                if (val === 'custom') {
                  setShowCustomDateUI(true);
                } else {
                  setShowCustomDateUI(false);
                }
              }}
              options={[
                { value: "month", label: "Este mês" },
                { value: "today", label: "Hoje" },
                { value: "week", label: "Esta semana" },
                { value: "all", label: "Todo o período" },
                { value: "custom", label: "Personalizado" },
              ]}
            />
            
            {periodType === 'custom' && !showCustomDateUI && (
              <button
                onClick={() => setShowCustomDateUI(true)}
                className="w-full py-1.5 px-3 rounded-lg border border-[var(--ks-color-primary-soft)] bg-[var(--ks-color-primary-light)] text-[var(--ks-color-primary-strong)] text-[10px] font-bold tracking-wide hover:bg-[var(--ks-color-primary-soft)] transition-colors flex items-center justify-between"
              >
                <span>{appliedCustomDates.start.split('-').reverse().join('/')} - {appliedCustomDates.end.split('-').reverse().join('/')}</span>
                <Edit2 size={12} />
              </button>
            )}
            
            {periodType === 'custom' && showCustomDateUI && (
              <>
                {/* Desktop Popover */}
                <div className="hidden lg:flex absolute top-full mt-2 right-0 w-full min-w-[280px] p-4 bg-white rounded-xl shadow-xl border border-[var(--ks-color-border-subtle)] z-40 flex-col gap-3 animate-in fade-in slide-in-from-top-2">
                  <div className="flex items-center gap-2">
                    <CustomDatePicker 
                      value={customStart}
                      onChange={setCustomStart}
                      placeholder="Data inicial"
                    />
                    <span className="text-[var(--ks-color-text-muted)] text-[10px] font-bold">até</span>
                    <CustomDatePicker 
                      value={customEnd}
                      onChange={setCustomEnd}
                      placeholder="Data final"
                    />
                  </div>
                  <button
                    onClick={() => {
                      setAppliedCustomDates({ start: customStart, end: customEnd });
                      setShowCustomDateUI(false);
                    }}
                    disabled={customStart === appliedCustomDates.start && customEnd === appliedCustomDates.end}
                    className="w-full py-2 rounded-lg bg-[var(--ks-color-primary)] text-white text-xs font-bold uppercase tracking-wider hover:bg-[var(--ks-color-primary-strong)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
                  >
                    Buscar
                  </button>
                </div>

                {/* Mobile Modal */}
                <div className="flex lg:hidden fixed inset-0 z-[100] items-center justify-center bg-black/40 px-4 animate-in fade-in">
                  <div className="bg-white rounded-2xl p-5 w-full max-w-sm shadow-2xl flex flex-col gap-4 animate-in zoom-in-95">
                    <div className="flex items-center justify-between">
                      <h3 className="font-bold text-[var(--ks-color-text-primary)]">Período Personalizado</h3>
                      <button 
                        onClick={() => setShowCustomDateUI(false)}
                        className="w-8 h-8 rounded-full flex items-center justify-center bg-[var(--ks-color-bg-subtle)] text-[var(--ks-color-text-muted)] hover:bg-gray-200"
                      >
                        <X size={16} />
                      </button>
                    </div>
                    
                    <div className="space-y-3">
                      <div>
                        <label className="text-[10px] uppercase font-bold text-[var(--ks-color-text-muted)] block mb-1">Data Inicial</label>
                        <CustomDatePicker 
                          value={customStart}
                          onChange={setCustomStart}
                          placeholder="Data inicial"
                        />
                      </div>
                      <div>
                        <label className="text-[10px] uppercase font-bold text-[var(--ks-color-text-muted)] block mb-1">Data Final</label>
                        <CustomDatePicker 
                          value={customEnd}
                          onChange={setCustomEnd}
                          placeholder="Data final"
                        />
                      </div>
                    </div>

                    <div className="flex gap-3 mt-2">
                      <button
                        onClick={() => setShowCustomDateUI(false)}
                        className="flex-1 py-2.5 rounded-xl border border-[var(--ks-color-border-subtle)] text-[var(--ks-color-text-muted)] text-xs font-bold uppercase tracking-wider hover:bg-gray-50"
                      >
                        Cancelar
                      </button>
                      <button
                        onClick={() => {
                          setAppliedCustomDates({ start: customStart, end: customEnd });
                          setShowCustomDateUI(false);
                        }}
                        disabled={customStart === appliedCustomDates.start && customEnd === appliedCustomDates.end}
                        className="flex-1 py-2.5 rounded-xl bg-[var(--ks-color-primary)] text-white text-xs font-bold uppercase tracking-wider hover:bg-[var(--ks-color-primary-strong)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
                      >
                        Buscar
                      </button>
                    </div>
                  </div>
                </div>
              </>
            )}
          </div>
        </div>
      </div>

      {/* Layout de Duas Colunas: Listagem (Esquerda) e Gráfico Circular (Direita) */}
      <div className="flex flex-col lg:flex-row gap-6 items-start w-full">
        
        {/* Coluna Principal: Busca e Lista de Contas */}
        <div className="flex-1 min-w-0 w-full space-y-4">
          
          {/* Filtro de Busca */}
          <div className="flex flex-col sm:flex-row gap-4 items-start sm:items-center justify-between">
            <div className="flex-1 max-w-md w-full">
              <Input
                placeholder="Buscar por cliente, empresa ou código..."
                value={searchTerm}
                onChange={(e) => setSearchTerm(e.target.value)}
                className="w-full"
              />
            </div>

            <div className="flex items-center gap-2">
              <div className="flex items-center gap-2 text-sm text-[var(--ks-color-text-muted)]">
                <FileText size={16} />
                <span>{filteredReceivables.length} conta(s) a receber</span>
              </div>
              {podeLancar && (
                <button
                  onClick={() => {
                    setShowCreateModal(true);
                  }}
                  className="inline-flex items-center gap-2 rounded-lg bg-[var(--ks-color-primary)] text-white px-3 py-2 text-xs font-bold uppercase tracking-wider hover:bg-[var(--ks-color-primary-strong)] transition-colors"
                >
                  <Plus size={14} />
                  Nova Conta
                </button>
              )}
            </div>
          </div>

          {/* Nova Listagem - Desktop */}
          <div className="hidden md:flex flex-col gap-3">
        {filteredReceivables.map((account) => (
          <div key={account.id} className="ks-surface p-4 xl:p-5 rounded-xl border border-[var(--ks-color-border-subtle)] hover:border-[var(--ks-color-primary-light)] hover:shadow-sm transition-all group grid grid-cols-1 xl:grid-cols-12 gap-4 xl:gap-6 items-start xl:items-center">
            
            <div className="flex items-center justify-between w-full xl:col-span-5 min-w-0 gap-4">
              {/* 1. Identificação do Pedido & Cliente */}
              <div className="flex items-center gap-3 xl:gap-4 flex-1 min-w-0">
                <div className="w-10 h-10 xl:w-12 xl:h-12 rounded-xl bg-[var(--ks-color-bg-subtle)] border border-[var(--ks-color-border-subtle)] flex flex-col items-center justify-center shrink-0 group-hover:bg-[var(--ks-color-primary-light)] group-hover:border-[var(--ks-color-primary-light)] transition-colors">
                  <span className="text-[8px] xl:text-[9px] font-bold text-[var(--ks-color-text-muted)] uppercase tracking-wider group-hover:text-[var(--ks-color-primary)]">{account.source === "order" ? "PED" : "REC"}</span>
                  <span className="text-xs xl:text-sm font-bold text-[var(--ks-color-text-primary)] group-hover:text-[var(--ks-color-primary)]">
                    {account.account_code}
                  </span>
                </div>
                <div className="flex flex-col min-w-0">
                  <span className="text-sm xl:text-base font-semibold text-[var(--ks-color-text-primary)] truncate" title={account.client_name}>
                    {account.client_name}
                  </span>
                  {account.client_company ? (
                    <span className="text-xs xl:text-sm text-[var(--ks-color-text-muted)] truncate" title={account.client_company}>
                      {account.client_company}
                    </span>
                  ) : (
                    <span className="text-xs xl:text-sm text-[var(--ks-color-text-muted)]">Consumidor Final</span>
                  )}
                </div>
              </div>

              {/* Barra de Progresso do Pedido */}
              <div className="flex flex-col shrink-0 w-[80px] xl:w-[100px] gap-1.5 hidden xl:flex">
                <div className="flex justify-between items-center text-[9px] xl:text-[10px] font-bold text-[var(--ks-color-text-muted)]">
                  <span>Progresso</span>
                  <span>{account.total_amount > 0 ? ((account.paid_amount / account.total_amount) * 100).toFixed(0) : 0}%</span>
                </div>
                <div className="h-1.5 w-full bg-[var(--ks-color-bg-subtle)] rounded-full overflow-hidden border border-[var(--ks-color-border-subtle)]">
                  <div 
                    className={`h-full rounded-full transition-all ${account.financial_status === 'paid' ? 'bg-emerald-500' : account.financial_status === 'partially_paid' ? 'bg-amber-500' : 'bg-transparent'}`}
                    style={{ width: `${account.total_amount > 0 ? (account.paid_amount / account.total_amount) * 100 : 0}%` }}
                  ></div>
                </div>
              </div>
            </div>

            <div className="flex items-center justify-end w-full xl:col-span-7 gap-4 xl:gap-6 pt-3 xl:pt-0 border-t xl:border-t-0 border-[var(--ks-color-border-subtle)]">
              {/* 2. Valores Financeiros (Grid Fixo para Alinhamento) */}
              <div className="grid grid-cols-2 lg:grid-cols-3 gap-4 xl:gap-6 shrink-0 flex-1">
                <div className="flex flex-col items-end justify-center border-r border-[var(--ks-color-border-subtle)] pr-4 xl:pr-6">
                  <span className="text-[9px] xl:text-[10px] font-bold uppercase tracking-wider text-[var(--ks-color-text-muted)] mb-1">Valor Total</span>
                  <span className="text-xs xl:text-sm font-medium text-[var(--ks-color-text-primary)]">{dinheiro(account.total_amount)}</span>
                </div>
                
                <div className="flex flex-col items-end justify-center hidden lg:flex border-r border-[var(--ks-color-border-subtle)] pr-4 xl:pr-6">
                  <span className="text-[9px] xl:text-[10px] font-bold uppercase tracking-wider text-[var(--ks-color-text-muted)] mb-1">Valor Pago</span>
                  <span className="text-xs xl:text-sm font-medium text-emerald-600">{dinheiro(account.paid_amount)}</span>
                </div>

                <div className="flex flex-col items-end justify-center">
                  <span className="text-[9px] xl:text-[10px] font-bold uppercase tracking-wider text-[var(--ks-color-text-muted)] mb-1">Saldo</span>
                  <span className={`text-sm xl:text-base font-bold ${account.balance > 0 ? 'text-orange-600' : 'text-emerald-600'}`}>
                    {dinheiro(account.balance)}
                  </span>
                </div>
              </div>

              {/* 3. Status e Ação
                  DUAS CAIXAS DE LARGURA FIXA, UMA PARA CADA COISA. Antes era uma
                  caixa só de 130 px dividida entre a pílula e os botões. Conta
                  PARCIAL mostra dois botões (receber o resto e estornar), que
                  comem 86 px; sobravam 28 px para a pílula "Parcial", e ela
                  vazava para a esquerda, em cima da palavra "Saldo". Separadas,
                  cada caixa tem o tamanho do seu pior caso e as colunas
                  continuam alinhadas de uma linha para a outra. */}
              <div className="flex items-center justify-end gap-3 xl:gap-4 shrink-0">
                <div className="flex justify-end shrink-0 w-[64px] xl:w-[72px]">
                  <span className={statusClass(account.financial_status)}>
                    {statusLabel(account.financial_status)}
                  </span>
                </div>
                {/* Tres situacoes, nao duas: em aberto so recebe; parcial pode
                    receber o resto ou desfazer o que ja entrou; quitado so
                    desfaz. Por isso os dois botoes convivem no meio, e a caixa
                    deles guarda lugar para dois mesmo quando mostra um. */}
                {!podeLancar ? null : (
                  <div className="flex items-center justify-end gap-1.5 shrink-0 w-[70px] xl:w-[86px]">
                {account.balance > 0.01 && (
                  <button
                    onClick={() => handleReceiveManual(account)}
                    className="w-8 h-8 xl:w-10 xl:h-10 shrink-0 flex items-center justify-center rounded-lg bg-emerald-50 text-emerald-600 hover:bg-emerald-500 hover:text-white transition-colors cursor-pointer"
                    title="Baixar Recebimento"
                  >
                    <DollarSign size={16} className="xl:w-[18px] xl:h-[18px]" />
                  </button>
                )}
                {account.paid_amount > 0.01 && (
                  <button
                    onClick={() => abrirEstorno(account)}
                    className="w-8 h-8 xl:w-10 xl:h-10 shrink-0 flex items-center justify-center rounded-lg bg-amber-50 text-amber-600 hover:bg-amber-500 hover:text-white transition-colors cursor-pointer"
                    title="Estornar recebimento"
                  >
                    <Undo2 size={16} className="xl:w-[18px] xl:h-[18px]" />
                  </button>
                )}
                  </div>
                )}
              </div>
            </div>
          </div>
        ))}
        
        {filteredReceivables.length === 0 && (
          <div className="ks-surface p-12 rounded-xl text-center border border-[var(--ks-color-border-subtle)] border-dashed">
            <div className="w-16 h-16 bg-[var(--ks-color-bg-subtle)] rounded-full flex items-center justify-center mx-auto mb-4">
              <DollarSign size={24} className="text-[var(--ks-color-text-muted)]" />
            </div>
            <p className="text-[var(--ks-color-text-muted)] font-medium">
              {searchTerm
                ? 'Nenhuma conta encontrada para esta busca'
                : periodType === 'all'
                  ? 'Nenhuma conta a receber cadastrada'
                  : 'Nenhuma conta a receber neste período'}
            </p>
            {/* Dizer so "nenhuma conta a receber" quando o filtro e que estava
                escondendo faz a pessoa achar que perdeu dado. */}
            {!searchTerm && periodType !== 'all' && (
              <button
                type="button"
                onClick={() => setPeriodType('all')}
                className="mt-3 text-sm font-semibold text-[var(--ks-color-primary-strong)] hover:underline"
              >
                Ver todo o período
              </button>
            )}
          </div>
        )}
      </div>

      {/* Tabela de Contas a Receber - Mobile */}
      <div className="flex flex-col gap-3 md:hidden">
        {filteredReceivables.length === 0 ? (
          <div className="ks-surface p-8 rounded-xl text-center border border-[var(--ks-color-border-subtle)] border-dashed">
            <div className="w-12 h-12 bg-[var(--ks-color-bg-subtle)] rounded-full flex items-center justify-center mx-auto mb-3">
              <DollarSign size={20} className="text-[var(--ks-color-text-muted)]" />
            </div>
            <p className="text-[var(--ks-color-text-muted)] text-sm font-medium">
              {searchTerm
                ? 'Nenhuma conta encontrada'
                : periodType === 'all'
                  ? 'Nenhuma conta a receber cadastrada'
                  : 'Nenhuma conta a receber neste período'}
            </p>
            {!searchTerm && periodType !== 'all' && (
              <button
                type="button"
                onClick={() => setPeriodType('all')}
                className="mt-2 text-sm font-semibold text-[var(--ks-color-primary-strong)] hover:underline"
              >
                Ver todo o período
              </button>
            )}
          </div>
        ) : (
          filteredReceivables.map((account) => (
            <div key={account.id} className="ks-surface p-4 rounded-xl border border-[var(--ks-color-border-subtle)] flex flex-col gap-4">
              
              {/* Topo do Card Mobile */}
              <div className="flex items-start justify-between gap-3">
                <div className="flex items-center gap-3 min-w-0">
                  <div className="w-10 h-10 rounded-lg bg-[var(--ks-color-bg-subtle)] border border-[var(--ks-color-border-subtle)] flex flex-col items-center justify-center shrink-0">
                    <span className="text-[8px] font-bold text-[var(--ks-color-text-muted)] uppercase tracking-wider">{account.source === "order" ? "PED" : "REC"}</span>
                    <span className="text-xs font-bold text-[var(--ks-color-text-primary)]">
                      {account.account_code}
                    </span>
                  </div>
                  <div className="flex flex-col min-w-0">
                    <span className="text-sm font-bold text-[var(--ks-color-text-primary)] truncate" title={account.client_name}>
                      {account.client_name}
                    </span>
                    {account.client_company ? (
                      <span className="text-xs text-[var(--ks-color-text-muted)] truncate">
                        {account.client_company}
                      </span>
                    ) : (
                      <span className="text-xs text-[var(--ks-color-text-muted)]">Consumidor Final</span>
                    )}
                  </div>
                </div>
                <div className="shrink-0">
                  <span className={statusClass(account.financial_status)}>
                    {statusLabel(account.financial_status)}
                  </span>
                </div>
              </div>

              {/* Grid Financeiro Mobile */}
              <div className="flex flex-col gap-3 p-3 bg-[var(--ks-color-bg-subtle)] rounded-lg">
                <div className="flex justify-between items-center text-[10px] font-bold text-[var(--ks-color-text-muted)]">
                  <span className="uppercase tracking-wider">Recebimento</span>
                  <span>{account.total_amount > 0 ? ((account.paid_amount / account.total_amount) * 100).toFixed(0) : 0}%</span>
                </div>
                <div className="h-1.5 w-full bg-white rounded-full overflow-hidden border border-[var(--ks-color-border-subtle)] mb-1">
                  <div 
                    className={`h-full rounded-full transition-all ${account.financial_status === 'paid' ? 'bg-emerald-500' : account.financial_status === 'partially_paid' ? 'bg-amber-500' : 'bg-transparent'}`}
                    style={{ width: `${account.total_amount > 0 ? (account.paid_amount / account.total_amount) * 100 : 0}%` }}
                  ></div>
                </div>

                <div className="grid grid-cols-3 gap-2">
                  <div className="flex flex-col">
                    <span className="text-[9px] font-bold uppercase tracking-wider text-[var(--ks-color-text-muted)] mb-0.5">Total</span>
                    <span className="text-xs font-medium text-[var(--ks-color-text-primary)]">{dinheiro(account.total_amount)}</span>
                  </div>
                  <div className="flex flex-col">
                    <span className="text-[9px] font-bold uppercase tracking-wider text-[var(--ks-color-text-muted)] mb-0.5">Pago</span>
                    <span className="text-xs font-medium text-emerald-600">{dinheiro(account.paid_amount)}</span>
                  </div>
                  <div className="flex flex-col items-end">
                    <span className="text-[9px] font-bold uppercase tracking-wider text-[var(--ks-color-text-muted)] mb-0.5">Saldo</span>
                    <span className={`text-sm font-bold ${account.balance > 0 ? 'text-orange-600' : 'text-emerald-600'}`}>
                      {dinheiro(account.balance)}
                    </span>
                  </div>
                </div>
              </div>

              {/* Botão Ação Mobile */}
              {!podeLancar ? null : (
                <div className="flex flex-col gap-2">
              {account.balance > 0.01 && (
                <button
                  onClick={() => handleReceiveManual(account)}
                  className="w-full flex items-center justify-center gap-2 py-2.5 rounded-lg border border-emerald-200 text-sm font-semibold text-emerald-700 hover:bg-emerald-500 hover:text-white hover:border-emerald-500 transition-colors"
                >
                  <DollarSign size={16} />
                  Baixar Recebimento
                </button>
              )}
              {account.paid_amount > 0.01 && (
                <button
                  onClick={() => abrirEstorno(account)}
                  className="w-full flex items-center justify-center gap-2 py-2.5 rounded-lg border border-amber-200 text-sm font-semibold text-amber-700 hover:bg-amber-500 hover:text-white hover:border-amber-500 transition-colors"
                >
                  <Undo2 size={16} />
                  Estornar recebimento
                </button>
              )}
                </div>
              )}
            </div>
          ))
        )}
      </div>
        </div>

        {/* Coluna Lateral: Gráfico de Saúde Financeira (Sticky) */}
        <div className="w-full lg:w-[260px] xl:w-[320px] shrink-0 sticky top-6 space-y-4">
          <div className="ks-surface p-6 rounded-xl border border-[var(--ks-color-border-subtle)]">
            <h3 className="text-sm font-bold uppercase tracking-wider text-[var(--ks-color-text-muted)] mb-6 flex items-center gap-2">
              <TrendingUp size={16} />
              Saúde Financeira
            </h3>
            
            <div className="relative w-48 h-48 mx-auto flex items-center justify-center">
              <svg className="w-full h-full transform -rotate-90" viewBox="0 0 100 100">
                {/* Círculo de fundo */}
                <circle
                  cx="50"
                  cy="50"
                  r="40"
                  fill="transparent"
                  stroke="var(--ks-color-bg-subtle)"
                  strokeWidth="8"
                />
                {/* Círculo de progresso */}
                <circle
                  cx="50"
                  cy="50"
                  r="40"
                  fill="transparent"
                  stroke="var(--ks-color-primary)"
                  strokeWidth="8"
                  strokeDasharray="251.2"
                  strokeDashoffset={251.2 - (251.2 * saudePercent) / 100}
                  strokeLinecap="round"
                  className="transition-all duration-1000 ease-out"
                />
              </svg>
              <div className="absolute inset-0 flex flex-col items-center justify-center">
                <span className="text-3xl font-black text-[var(--ks-color-text-primary)]">
                  {saudePercent.toFixed(0)}%
                </span>
                <span className="text-[10px] font-bold uppercase tracking-wider text-[var(--ks-color-text-muted)]">
                  Recebido
                </span>
              </div>
            </div>

            <div className="mt-8 space-y-4">
              <div className="flex justify-between items-center text-sm">
                <div className="flex items-center gap-2">
                  <div className="w-3 h-3 rounded-full bg-[var(--ks-color-primary)]"></div>
                  <span className="font-medium text-[var(--ks-color-text-muted)]">Recebido</span>
                </div>
                <span className="font-bold text-[var(--ks-color-text-primary)]">{dinheiro(totalRecebido)}</span>
              </div>
              <div className="flex justify-between items-center text-sm">
                <div className="flex items-center gap-2">
                  <div className="w-3 h-3 rounded-full bg-rose-50 border border-rose-200"></div>
                  <span className="font-medium text-[var(--ks-color-text-muted)]">A Receber</span>
                </div>
                <span className="font-bold text-[var(--ks-color-text-primary)]">{dinheiro(totalFaturado - totalRecebido)}</span>
              </div>
            </div>
          </div>
        </div>

      </div>

      {showEstornoModal && estornoTarget && (
        <div className="fixed inset-0 z-[130] bg-black/40 flex items-center justify-center p-4">
          <div className="ks-surface w-full max-w-lg rounded-3xl border border-[var(--ks-color-border-subtle)] p-6 space-y-4 shadow-2xl">
            <div className="flex items-start justify-between gap-3">
              <div className="min-w-0">
                <h3 className="text-lg font-black text-[var(--ks-color-text-primary)]">Estornar recebimento</h3>
                <p className="text-xs text-[var(--ks-color-text-muted)] truncate">
                  {estornoTarget.account_code} · {estornoTarget.client_name}
                </p>
              </div>
              <button
                type="button"
                onClick={() => setShowEstornoModal(false)}
                className="h-9 w-9 inline-flex items-center justify-center rounded-full hover:bg-[var(--ks-color-bg-hover)]"
              >
                <X size={18} className="text-[var(--ks-color-text-muted)]" />
              </button>
            </div>

            {estornoError && (
              <div className="rounded-xl bg-[var(--ks-color-status-danger-soft)] px-3 py-2 text-sm text-[var(--ks-color-status-danger)]">
                {estornoError}
              </div>
            )}

            {estornoCarregando ? (
              <p className="text-sm text-[var(--ks-color-text-muted)] py-6 text-center">Carregando recebimentos…</p>
            ) : estornoTarget.ehPdv ? (
              <div className="space-y-3">
                <p className="text-sm text-[var(--ks-color-text-secondary)]">
                  Esta é uma venda de balcão. O estorno de uma venda do PDV desfaz todos os
                  pagamentos e cancela a venda no mesmo passo — não dá para estornar só uma parte.
                </p>
                <div className="rounded-xl bg-[var(--ks-color-bg-inset)] px-3 py-2.5 text-sm">
                  {estornoLista.length === 0 ? (
                    <span className="text-[var(--ks-color-text-soft)]">Sem pagamentos registrados.</span>
                  ) : (
                    <>
                      <span className="font-bold text-[var(--ks-color-text-primary)]">
                        {dinheiro(estornoLista.reduce((soma, l) => soma + l.amount, 0))}
                      </span>
                      <span className="text-[var(--ks-color-text-soft)]">
                        {" "}em {estornoLista.length}{" "}
                        {estornoLista.length === 1 ? "pagamento" : "pagamentos"} serão estornados.
                      </span>
                    </>
                  )}
                </div>
                <button
                  type="button"
                  onClick={() => void cancelarVendaPdv()}
                  disabled={estornandoId !== null}
                  className="w-full inline-flex items-center justify-center gap-2 rounded-xl bg-amber-500 px-4 py-2.5 text-sm font-bold text-white transition hover:bg-amber-600 disabled:opacity-50 disabled:cursor-not-allowed"
                >
                  <Undo2 size={16} />
                  {estornandoId === "pdv" ? "Cancelando…" : "Cancelar venda e estornar"}
                </button>
              </div>
            ) : estornoLista.length === 0 ? (
              <div className="space-y-3 py-2">
                <p className="text-sm text-[var(--ks-color-text-muted)] text-center">
                  Nenhum recebimento para estornar.
                </p>
                {estornoTarget.source === "order" && (
                  <>
                    <p className="text-xs text-[var(--ks-color-text-soft)] text-center">
                      O pedido continua na carteira devendo o valor cheio. Se a venda não vai
                      acontecer, cancele para tirá-lo daqui.
                    </p>
                    <button
                      type="button"
                      onClick={() => void cancelarPedido()}
                      disabled={estornandoId !== null}
                      className="w-full inline-flex items-center justify-center gap-2 rounded-xl border border-[var(--ks-color-status-danger)] px-4 py-2.5 text-sm font-bold text-[var(--ks-color-status-danger)] transition hover:bg-[var(--ks-color-status-danger)] hover:text-white disabled:opacity-50 disabled:cursor-not-allowed"
                    >
                      <X size={16} />
                      {estornandoId === "cancelar" ? "Cancelando…" : "Cancelar o pedido"}
                    </button>
                  </>
                )}
              </div>
            ) : (
              <>
                <p className="text-xs text-[var(--ks-color-text-soft)]">
                  Escolha qual recebimento desfazer. O valor volta para o saldo do título e sai do
                  caixa em que entrou.
                </p>
                <div className="space-y-2 max-h-[46vh] overflow-y-auto">
                  {estornoLista.map((lancamento) => (
                    <div
                      key={lancamento.id}
                      className="flex items-center justify-between gap-3 rounded-xl border border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-inset)] px-3 py-2.5"
                    >
                      <div className="min-w-0">
                        <div className="text-sm font-bold text-[var(--ks-color-text-primary)]">
                          {dinheiro(lancamento.amount)}
                        </div>
                        <div className="text-[11px] text-[var(--ks-color-text-soft)]">
                          {formatarData(lancamento.data)} · {rotuloDaForma(lancamento.forma)}
                        </div>
                      </div>
                      <button
                        type="button"
                        onClick={() => void estornarLancamento(lancamento)}
                        disabled={estornandoId !== null}
                        className="shrink-0 inline-flex items-center gap-1.5 rounded-lg border border-amber-200 px-3 py-1.5 text-xs font-semibold text-amber-700 transition hover:bg-amber-500 hover:text-white hover:border-amber-500 disabled:opacity-50 disabled:cursor-not-allowed"
                      >
                        <Undo2 size={14} />
                        {estornandoId === lancamento.id ? "Estornando…" : "Estornar"}
                      </button>
                    </div>
                  ))}
                </div>
              </>
            )}
          </div>
        </div>
      )}

      {showReceiveModal && receiveTarget && (
        <div className="fixed inset-0 z-[125] bg-black/45 flex items-center justify-center p-4">
          <div className="ks-surface w-full max-w-lg rounded-3xl border border-[var(--ks-color-border-subtle)] p-6 space-y-5 shadow-2xl">
            <div className="flex items-center justify-between">
              <div>
                <h3 className="text-lg font-black text-[var(--ks-color-text-primary)]">Baixar Recebimento</h3>
                <p className="text-xs text-[var(--ks-color-text-muted)] mt-0.5">{receiveTarget.client_name}</p>
              </div>
              <button
                onClick={() => {
                  setShowReceiveModal(false);
                  setReceiveTarget(null);
                  setReceiveError("");
                }}
                className="w-8 h-8 rounded-full bg-[var(--ks-color-bg-subtle)] flex items-center justify-center text-[var(--ks-color-text-muted)] hover:bg-gray-200"
              >
                <X size={16} />
              </button>
            </div>

            <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
              <Input
                placeholder="Valor recebido (R$)"
                value={receiveForm.amount}
                onChange={(e) => setReceiveForm((v) => ({ ...v, amount: maskCurrencyInput(e.target.value) }))}
              />
              <CustomDatePicker
                value={receiveForm.received_at}
                onChange={(date) => setReceiveForm((v) => ({ ...v, received_at: date }))}
                placeholder="Data do recebimento"
              />
              <div className="sm:col-span-2">
                <CustomSelect
                  value={receiveForm.payment_method}
                  onChange={(paymentMethod) =>
                    setReceiveForm((v) => ({ ...v, payment_method: paymentMethod, bank_account_id: "" }))
                  }
                  placeholder="Forma de recebimento *"
                  options={[
                    { value: "", label: "Forma de recebimento *" },
                    ...paymentMethodOptions,
                  ]}
                />
              </div>
              <div className="sm:col-span-2">
                <CustomSelect
                  value={receiveForm.bank_account_id}
                  onChange={(bankId) => setReceiveForm((v) => ({ ...v, bank_account_id: bankId }))}
                  placeholder={receiveAccountLabel}
                  searchable
                  options={[
                    { value: "", label: receiveAccountLabel },
                    ...receiveCompatibleAccounts.map((bank) => ({
                      value: bank.bank_account_id,
                      label: (bank.name || resolveBankDisplayName(bank.bank_name || "") || "Conta").trim(),
                      selected_label: (bank.name || resolveBankDisplayName(bank.bank_name || "") || "Conta").trim(),
                      description: bank.bank_name || undefined,
                      image_url: resolveLogoSrc(bank.logo_key ?? null, bank.bank_code ?? null, bank.bank_name ?? null),
                    })),
                  ]}
                />
              </div>
            </div>

            <div className="flex items-center gap-2">
              <button
                type="button"
                onClick={() =>
                  setReceiveForm((v) => ({
                    ...v,
                    amount: maskCurrencyInput(String(Math.round((receiveTarget.balance > 0 ? receiveTarget.balance : 0) * 100))),
                  }))
                }
                className="px-3 py-1.5 rounded-lg border border-emerald-200 bg-emerald-50 text-emerald-700 text-xs font-bold uppercase tracking-wider hover:bg-emerald-100 transition-colors cursor-pointer"
              >
                Saldo Total
              </button>
              <button
                type="button"
                onClick={() =>
                  setReceiveForm((v) => ({
                    ...v,
                    amount: maskCurrencyInput(
                      String(Math.round(((receiveTarget.balance > 0 ? receiveTarget.balance : 0) * 0.5) * 100))
                    ),
                  }))
                }
                className="px-3 py-1.5 rounded-lg border border-amber-200 bg-amber-50 text-amber-700 text-xs font-bold uppercase tracking-wider hover:bg-amber-100 transition-colors cursor-pointer"
              >
                50%
              </button>
              <button
                type="button"
                onClick={() => setReceiveForm((v) => ({ ...v, amount: "" }))}
                className="px-3 py-1.5 rounded-lg border border-[var(--ks-color-border-subtle)] bg-white text-[var(--ks-color-text-muted)] text-xs font-bold uppercase tracking-wider hover:bg-gray-50 transition-colors cursor-pointer"
              >
                Outro
              </button>
            </div>

            {receiveError ? (
              <div className="rounded-xl border border-rose-200 bg-rose-50 px-3 py-2 text-xs text-rose-700">
                {receiveError}
              </div>
            ) : null}

            <div className="flex items-center justify-end gap-2 pt-1">
              <button
                onClick={() => {
                  setShowReceiveModal(false);
                  setReceiveTarget(null);
                  setReceiveError("");
                }}
                className="px-4 py-2 rounded-lg border border-[var(--ks-color-border-subtle)] text-sm font-semibold text-[var(--ks-color-text-muted)] hover:bg-gray-50"
              >
                Cancelar
              </button>
              <button
                onClick={submitReceiveManual}
                disabled={receiving}
                className="px-4 py-2 rounded-lg bg-emerald-600 text-white text-sm font-semibold hover:bg-emerald-700 disabled:opacity-50"
              >
                {receiving ? "Baixando..." : "Confirmar Baixa"}
              </button>
            </div>
          </div>
        </div>
      )}

      {showCreateModal && (
        <div className="fixed inset-0 z-[120] bg-black/40 flex items-center justify-center p-4">
          <div className="ks-surface w-full max-w-xl rounded-3xl border border-[var(--ks-color-border-subtle)] p-6 space-y-5 shadow-2xl">
            <div className="flex items-center justify-between">
              <div>
                <h3 className="text-lg font-black text-[var(--ks-color-text-primary)]">Nova Conta a Receber</h3>
                <p className="text-xs text-[var(--ks-color-text-muted)] mt-0.5">Crie um recebível manual com padrão financeiro.</p>
              </div>
              <button
                onClick={() => {
                  setShowCreateModal(false);
                }}
                className="w-8 h-8 rounded-full bg-[var(--ks-color-bg-subtle)] flex items-center justify-center text-[var(--ks-color-text-muted)] hover:bg-gray-200"
              >
                <X size={16} />
              </button>
            </div>

            <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
              <Input
                placeholder="Descrição da conta *"
                value={newAccount.description}
                onChange={(e) => setNewAccount((v) => ({ ...v, description: e.target.value }))}
                className="sm:col-span-2"
              />
              <div className="sm:col-span-2">
                <CustomSelect
                  value={newAccount.client_id}
                  onChange={(clientId) => {
                    const client = clients.find((c) => c.id === clientId);
                    setNewAccount((v) => ({
                      ...v,
                      client_id: clientId,
                      client_name: client ? client.name : v.client_name,
                      client_company: client ? (client.company_name ?? "") : v.client_company,
                    }));
                  }}
                  placeholder="Buscar cliente cadastrado (opcional)"
                  searchable
                  options={[
                    { value: "", label: "Sem cliente vinculado" },
                    ...clients.map((client) => ({
                      value: client.id,
                      label: client.company_name ? `${client.name} - ${client.company_name}` : client.name,
                      selected_label: client.name,
                    })),
                  ]}
                />
              </div>
              <Input
                placeholder="Cliente"
                value={newAccount.client_name}
                onChange={(e) => setNewAccount((v) => ({ ...v, client_name: e.target.value }))}
              />
              <Input
                placeholder="Empresa"
                value={newAccount.client_company}
                onChange={(e) => setNewAccount((v) => ({ ...v, client_company: e.target.value }))}
              />
              <Input
                placeholder="Valor (R$) *"
                value={newAccount.total_amount}
                onChange={(e) => setNewAccount((v) => ({ ...v, total_amount: maskCurrencyInput(e.target.value) }))}
              />
              <div className="w-full">
                <CustomDatePicker
                value={newAccount.due_date}
                  onChange={(date) => setNewAccount((v) => ({ ...v, due_date: date }))}
                  placeholder="Vencimento *"
                />
              </div>
              <div className="sm:col-span-2">
                <CustomSelect
                  value={newAccount.bank_account_id}
                  onChange={(bankId) => setNewAccount((v) => ({ ...v, bank_account_id: bankId }))}
                  placeholder="Selecione a conta bancária *"
                  searchable
                  options={[
                    { value: "", label: "Selecione a conta bancária *" },
                    ...bankAccounts.map((bank) => ({
                      value: bank.bank_account_id,
                      label: (bank.name || resolveBankDisplayName(bank.bank_name || "") || "Conta bancária").trim(),
                      selected_label: (bank.name || resolveBankDisplayName(bank.bank_name || "") || "Conta bancária").trim(),
                      description: bank.bank_name || undefined,
                      image_url: resolveLogoSrc(bank.logo_key ?? null, bank.bank_code ?? null, bank.bank_name ?? null),
                    })),
                  ]}
                />
              </div>
            </div>

            <div className="flex items-center justify-end gap-2 pt-2">
              <button
                onClick={() => setShowCreateModal(false)}
                className="px-4 py-2 rounded-lg border border-[var(--ks-color-border-subtle)] text-sm font-semibold text-[var(--ks-color-text-muted)] hover:bg-gray-50"
              >
                Cancelar
              </button>
              <button
                onClick={handleCreateManualReceivable}
                disabled={creating}
                className="px-4 py-2 rounded-lg bg-[var(--ks-color-primary)] text-white text-sm font-semibold hover:bg-[var(--ks-color-primary-strong)] disabled:opacity-50"
              >
                {creating ? "Salvando..." : "Criar Conta"}
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
