"use client";
import { RiAddLine, RiDeleteBinLine } from "@remixicon/react";
import { useMemo, useState } from "react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { CurrencyInput } from "@/components/ui/currency-input";
import { DatePicker } from "@/components/ui/date-picker";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { Label } from "@/components/ui/label";
import { MonthPicker } from "@/components/ui/monthpicker";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Separator } from "@/components/ui/separator";
import { Spinner } from "@/components/ui/spinner";
import { groupAndSortCategorias } from "@/lib/lancamentos/categoria-helpers";
import { LANCAMENTO_PAYMENT_METHODS } from "@/lib/lancamentos/constants";
import { getTodayDateString } from "@/lib/utils/date";
import { displayPeriod } from "@/lib/utils/period";
import type { SelectOption } from "../../types";
import {
CategoriaSelectContent,
ContaCartaoSelectContent,
PagadorSelectContent,
PaymentMethodSelectContent,
TransactionTypeSelectContent,
} from "../select-items";
import { EstabelecimentoInput } from "../shared/estabelecimento-input";
/** Payment methods sem Boleto para este modal */
const MASS_ADD_PAYMENT_METHODS = LANCAMENTO_PAYMENT_METHODS.filter(
(m) => m !== "Boleto",
);
function periodToDate(period: string): Date {
const [year, month] = period.split("-").map(Number);
return new Date(year, month - 1, 1);
}
function dateToPeriod(date: Date): string {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
return `${year}-${month}`;
}
function InlinePeriodPicker({
period,
onPeriodChange,
}: {
period: string;
onPeriodChange: (value: string) => void;
}) {
const [open, setOpen] = useState(false);
return (
Fatura de
{
onPeriodChange(dateToPeriod(date));
setOpen(false);
}}
/>
);
}
interface MassAddDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
onSubmit: (data: MassAddFormData) => Promise;
pagadorOptions: SelectOption[];
contaOptions: SelectOption[];
cartaoOptions: SelectOption[];
categoriaOptions: SelectOption[];
estabelecimentos: string[];
selectedPeriod: string;
defaultPagadorId?: string | null;
defaultCartaoId?: string | null;
}
export interface MassAddFormData {
fixedFields: {
transactionType?: string;
paymentMethod?: string;
condition?: string;
period?: string;
contaId?: string;
cartaoId?: string;
};
transactions: Array<{
purchaseDate: string;
name: string;
amount: string;
categoriaId?: string;
pagadorId?: string;
}>;
}
interface TransactionRow {
id: string;
purchaseDate: string;
name: string;
amount: string;
categoriaId: string | undefined;
pagadorId: string | undefined;
}
export function MassAddDialog({
open,
onOpenChange,
onSubmit,
pagadorOptions,
contaOptions,
cartaoOptions,
categoriaOptions,
estabelecimentos,
selectedPeriod,
defaultPagadorId,
defaultCartaoId,
}: MassAddDialogProps) {
const [loading, setLoading] = useState(false);
// Fixed fields state (sempre ativos, sem checkboxes)
const [transactionType, setTransactionType] = useState("Despesa");
const [paymentMethod, setPaymentMethod] = useState(
LANCAMENTO_PAYMENT_METHODS[0],
);
const [period, setPeriod] = useState(selectedPeriod);
const [contaId, setContaId] = useState(undefined);
const [cartaoId, setCartaoId] = useState(
defaultCartaoId ?? undefined,
);
// Quando defaultCartaoId está definido, exibe apenas o cartão específico
const isLockedToCartao = !!defaultCartaoId;
const isCartaoSelected = paymentMethod === "Cartão de crédito";
// Transaction rows
const [transactions, setTransactions] = useState([
{
id: crypto.randomUUID(),
purchaseDate: getTodayDateString(),
name: "",
amount: "",
categoriaId: undefined,
pagadorId: defaultPagadorId ?? undefined,
},
]);
// Categorias agrupadas e filtradas por tipo de transação
const groupedCategorias = useMemo(() => {
const filtered = categoriaOptions.filter(
(option) => option.group?.toLowerCase() === transactionType.toLowerCase(),
);
return groupAndSortCategorias(filtered);
}, [categoriaOptions, transactionType]);
const addTransaction = () => {
setTransactions([
...transactions,
{
id: crypto.randomUUID(),
purchaseDate: getTodayDateString(),
name: "",
amount: "",
categoriaId: undefined,
pagadorId: defaultPagadorId ?? undefined,
},
]);
};
const removeTransaction = (id: string) => {
if (transactions.length === 1) {
toast.error("É necessário ter pelo menos uma transação");
return;
}
setTransactions(transactions.filter((t) => t.id !== id));
};
const updateTransaction = (
id: string,
field: keyof TransactionRow,
value: string | undefined,
) => {
setTransactions(
transactions.map((t) => (t.id === id ? { ...t, [field]: value } : t)),
);
};
const handleSubmit = async () => {
// Validate conta/cartao selection
if (isCartaoSelected && !cartaoId) {
toast.error("Selecione um cartão para continuar");
return;
}
if (!isCartaoSelected && !contaId) {
toast.error("Selecione uma conta para continuar");
return;
}
// Validate transactions
const invalidTransactions = transactions.filter(
(t) => !t.name.trim() || !t.amount.trim() || !t.purchaseDate,
);
if (invalidTransactions.length > 0) {
toast.error(
"Preencha todos os campos obrigatórios das transações (data, estabelecimento e valor)",
);
return;
}
// Build form data
const formData: MassAddFormData = {
fixedFields: {
transactionType,
paymentMethod,
condition: "À vista",
period,
contaId,
cartaoId,
},
transactions: transactions.map((t) => ({
purchaseDate: t.purchaseDate,
name: t.name.trim(),
amount: t.amount.trim(),
categoriaId: t.categoriaId,
pagadorId: t.pagadorId,
})),
};
setLoading(true);
try {
await onSubmit(formData);
onOpenChange(false);
// Reset form
setTransactionType("Despesa");
setPaymentMethod(LANCAMENTO_PAYMENT_METHODS[0]);
setPeriod(selectedPeriod);
setContaId(undefined);
setCartaoId(defaultCartaoId ?? undefined);
setTransactions([
{
id: crypto.randomUUID(),
purchaseDate: getTodayDateString(),
name: "",
amount: "",
categoriaId: undefined,
pagadorId: defaultPagadorId ?? undefined,
},
]);
} catch (_error) {
// Error is handled by the onSubmit function
} finally {
setLoading(false);
}
};
return (
);
}