"use client";

import { Button } from "@/shared/components/ui/button";
import { Checkbox } from "@/shared/components/ui/checkbox";
import { CurrencyInput } from "@/shared/components/ui/currency-input";
import {
	Dialog,
	DialogContent,
	DialogDescription,
	DialogFooter,
	DialogHeader,
	DialogTitle,
} from "@/shared/components/ui/dialog";
import { Input } from "@/shared/components/ui/input";
import { formatCurrency } from "@/shared/utils/currency";
import { safeToNumber } from "@/shared/utils/number";
import { cn } from "@/shared/utils/ui";
import { PayerSelectContent } from "../../select-items";
import type { FormState } from "./transaction-dialog-types";

const splitRowClassName =
	"grid min-h-[2rem] items-center gap-2 rounded-lg border p-1.5 transition-colors sm:grid-cols-[minmax(0,1fr)_7rem_5.5rem]";
const splitDisabledFieldClassName =
	"hidden h-9 rounded-md border border-transparent sm:block";

type SplitConfigDialogProps = {
	open: boolean;
	onOpenChange: (open: boolean) => void;
	formState: FormState;
	onFieldChange: <Key extends keyof FormState>(
		key: Key,
		value: FormState[Key],
	) => void;
	payerOptions: Array<{
		value: string;
		label: string;
		role?: string | null;
		avatarUrl?: string | null;
	}>;
	splitPayerOptions: Array<{
		value: string;
		label: string;
		avatarUrl?: string | null;
	}>;
	totalAmount: number;
};

const getPercentValue = (amount: string, totalAmount: number) => {
	if (totalAmount <= 0) return "0%";
	const percentage = (safeToNumber(amount) / totalAmount) * 100;
	return percentage.toLocaleString("pt-BR", {
		maximumFractionDigits: 1,
	});
};

const percentToAmount = (percent: string, totalAmount: number) => {
	const normalized = percent.replace(/[^\d.,]/g, "").replace(",", ".");
	const percentage = Number(normalized);

	if (!Number.isFinite(percentage) || totalAmount <= 0) return "0.00";

	const clamped = Math.min(100, Math.max(0, percentage));
	return ((totalAmount * clamped) / 100).toFixed(2);
};

const getEqualAmounts = (count: number, totalAmount: number) => {
	if (count <= 0 || totalAmount <= 0) return [];

	const centsTotal = Math.round(totalAmount * 100);
	const baseCents = Math.floor(centsTotal / count);
	let remainder = centsTotal - baseCents * count;

	return Array.from({ length: count }, () => {
		const cents = baseCents + (remainder > 0 ? 1 : 0);
		remainder -= 1;
		return (cents / 100).toFixed(2);
	});
};

type SplitSummaryPayerOption = {
	value: string;
	label: string;
	avatarUrl?: string | null;
};

export function getSplitSummaryData(
	formState: FormState,
	payerOptions: SplitSummaryPayerOption[],
	totalAmount: number,
) {
	if (!formState.isSplit) {
		return {
			type: "text" as const,
			label: "Atribuir partes do valor a outras pessoas.",
		};
	}

	const participants = [
		formState.payerId,
		...formState.splitShares.map((share) => share.payerId),
	].filter(Boolean);

	if (participants.length <= 1) {
		return {
			type: "text" as const,
			label: "Configure as pessoas e os valores da divisão.",
		};
	}

	const total =
		safeToNumber(formState.primarySplitAmount) +
		formState.splitShares.reduce(
			(sum, share) => sum + safeToNumber(share.amount),
			0,
		);
	const displayedParticipants = participants
		.slice(0, 3)
		.map((payerId) => payerOptions.find((option) => option.value === payerId))
		.filter(Boolean)
		.map((option) => ({
			label: option?.label ?? "",
			firstName: option?.label.split(/\s+/)[0] ?? "",
			avatarUrl: option?.avatarUrl ?? null,
		}));
	const remainingCount = Math.max(0, participants.length - 3);
	const totalLabel =
		Math.abs(total - totalAmount) <= 0.01
			? formatCurrency(totalAmount)
			: `${formatCurrency(total)} de ${formatCurrency(totalAmount)}`;

	return {
		type: "split" as const,
		count: participants.length,
		participants: displayedParticipants,
		remainingCount,
		totalLabel,
	};
}

export function SplitConfigDialog({
	open,
	onOpenChange,
	formState,
	onFieldChange,
	payerOptions,
	splitPayerOptions,
	totalAmount,
}: SplitConfigDialogProps) {
	const selectedSplitIds = new Set(
		formState.splitShares.map((share) => share.payerId),
	);
	const availableSplitOptions = splitPayerOptions.filter(
		(option) => option.value !== formState.payerId,
	);
	const primaryPayerOption =
		payerOptions.find((option) => option.value === formState.payerId) ??
		payerOptions.find((option) => option.role === "admin") ??
		null;
	const splitTotal =
		safeToNumber(formState.primarySplitAmount) +
		formState.splitShares.reduce(
			(total, share) => total + safeToNumber(share.amount),
			0,
		);
	const splitDifference = totalAmount - splitTotal;
	const hasSplitDifference = Math.abs(splitDifference) > 0.01;
	const splitDifferenceLabel =
		splitDifference > 0
			? `Faltam ${formatCurrency(splitDifference)}`
			: `Sobram ${formatCurrency(Math.abs(splitDifference))}`;

	const applyEqualSplit = (shares = formState.splitShares) => {
		const participantCount = (formState.payerId ? 1 : 0) + shares.length;
		const amounts = getEqualAmounts(participantCount, totalAmount);

		if (amounts.length === 0) return;

		onFieldChange("primarySplitAmount", amounts[0] ?? "0.00");
		onFieldChange(
			"splitShares",
			shares.map((share, index) => ({
				...share,
				amount: amounts[index + 1] ?? "0.00",
			})),
		);
	};

	const toggleSplitPayer = (payerId: string, checked: boolean) => {
		const nextShares = checked
			? [...formState.splitShares, { payerId, amount: "0.00" }]
			: formState.splitShares.filter((share) => share.payerId !== payerId);

		applyEqualSplit(nextShares);
	};

	const handleSecondaryAmountChange = (payerId: string, value: string) => {
		const nextShares = formState.splitShares.map((share) =>
			share.payerId === payerId ? { ...share, amount: value } : share,
		);
		const othersTotal = nextShares.reduce(
			(total, share) => total + safeToNumber(share.amount),
			0,
		);

		onFieldChange("splitShares", nextShares);
		onFieldChange(
			"primarySplitAmount",
			Math.max(0, totalAmount - othersTotal).toFixed(2),
		);
	};

	const handleSecondaryPercentChange = (payerId: string, percent: string) => {
		handleSecondaryAmountChange(payerId, percentToAmount(percent, totalAmount));
	};

	const handleDisableSplit = () => {
		onFieldChange("isSplit", false);
		onOpenChange(false);
	};

	const renderPercentInput = (
		amount: string,
		onPercentChange: (percent: string) => void,
		ariaLabel: string,
	) => (
		<div className="relative">
			<Input
				type="text"
				inputMode="decimal"
				value={getPercentValue(amount, totalAmount)}
				onChange={(event) => onPercentChange(event.target.value)}
				placeholder="0"
				aria-label={ariaLabel}
				className="h-9 pr-7 text-sm"
			/>
			<span className="pointer-events-none absolute top-1/2 right-2 -translate-y-1/2 text-xs text-muted-foreground">
				%
			</span>
		</div>
	);

	return (
		<Dialog open={open} onOpenChange={onOpenChange}>
			<DialogContent className="flex max-h-[90vh] min-w-0 flex-col overflow-hidden sm:max-w-lg">
				<DialogHeader>
					<DialogTitle>Dividir lançamento</DialogTitle>
					<DialogDescription>
						Marque as pessoas e ajuste os valores se precisar.
					</DialogDescription>
				</DialogHeader>

				<div className="min-h-0 space-y-2 overflow-y-auto pr-1">
					<div
						className={cn(
							"flex flex-wrap items-center justify-between gap-2 rounded-lg border px-3 py-2.5",
							hasSplitDifference
								? "border-destructive/30 bg-destructive/5"
								: "border-primary/20 bg-primary/5",
						)}
					>
						<div>
							<p className="text-sm font-medium">
								{formatCurrency(splitTotal)} de {formatCurrency(totalAmount)}
							</p>
							<p
								className={cn(
									"text-xs",
									hasSplitDifference
										? "text-destructive"
										: "text-muted-foreground",
								)}
							>
								{hasSplitDifference ? splitDifferenceLabel : "Tudo certo"}
							</p>
						</div>
						<Button
							type="button"
							variant="outline"
							size="sm"
							onClick={() => applyEqualSplit()}
							disabled={
								totalAmount <= 0 ||
								!formState.payerId ||
								formState.splitShares.length === 0
							}
							className="border-primary/30 bg-primary/10 text-primary hover:bg-primary/15 hover:text-primary"
						>
							Dividir igualmente
						</Button>
					</div>

					<div className="space-y-2">
						{primaryPayerOption ? (
							<div className={cn(splitRowClassName, "bg-background")}>
								<div className="flex min-w-0 items-center gap-2 text-sm">
									<Checkbox checked disabled aria-hidden />
									<PayerSelectContent
										label={primaryPayerOption.label}
										avatarUrl={primaryPayerOption.avatarUrl}
									/>
								</div>
								<CurrencyInput
									value={formState.primarySplitAmount}
									onValueChange={(value) =>
										onFieldChange("primarySplitAmount", value)
									}
									placeholder="R$ 0,00"
									aria-label={`Valor de ${primaryPayerOption.label}`}
									className="h-9 text-sm"
								/>
								{renderPercentInput(
									formState.primarySplitAmount,
									(percent) =>
										onFieldChange(
											"primarySplitAmount",
											percentToAmount(percent, totalAmount),
										),
									`Percentual de ${primaryPayerOption.label}`,
								)}
							</div>
						) : null}

						{availableSplitOptions.map((option) => {
							const isSelected = selectedSplitIds.has(option.value);
							const share = formState.splitShares.find(
								(item) => item.payerId === option.value,
							);

							return (
								<div
									key={option.value}
									className={cn(
										splitRowClassName,
										isSelected
											? "bg-background"
											: "border-border/60 bg-muted/20 opacity-60",
									)}
								>
									<label className="flex min-w-0 cursor-pointer items-center gap-2 text-sm">
										<Checkbox
											checked={isSelected}
											onCheckedChange={(checked) =>
												toggleSplitPayer(option.value, Boolean(checked))
											}
										/>
										<span className="min-w-0 flex-1">
											<PayerSelectContent
												label={option.label}
												avatarUrl={option.avatarUrl}
											/>
										</span>
									</label>
									{isSelected && share ? (
										<>
											<CurrencyInput
												value={share.amount}
												onValueChange={(value) =>
													handleSecondaryAmountChange(option.value, value)
												}
												placeholder="R$ 0,00"
												aria-label={`Valor de ${option.label}`}
												className="h-9 text-sm"
											/>
											{renderPercentInput(
												share.amount,
												(percent) =>
													handleSecondaryPercentChange(option.value, percent),
												`Percentual de ${option.label}`,
											)}
										</>
									) : (
										<>
											<div className={splitDisabledFieldClassName} />
											<div className={splitDisabledFieldClassName} />
										</>
									)}
								</div>
							);
						})}
					</div>
				</div>

				<DialogFooter className="shrink-0">
					<Button type="button" variant="outline" onClick={handleDisableSplit}>
						Cancelar divisão
					</Button>
					<Button type="button" onClick={() => onOpenChange(false)}>
						Concluir
					</Button>
				</DialogFooter>
			</DialogContent>
		</Dialog>
	);
}
