import InputError from '@/components/input-error';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { useTranslation } from '@/hooks/use-translation';
import { Link, useForm } from '@inertiajs/react';
import { AlertTriangle, Copy, CreditCard } from 'lucide-react';
import { useEffect, useState } from 'react';
import { toast } from 'sonner';

export interface OpenPaymentLink {
    id: number;
    order_number: string;
    amount: string;
    form_url: string | null;
    expires_at: string | null;
}

interface Props {
    open: boolean;
    onOpenChange: (open: boolean) => void;
    reservationId: number;
    /** Ce qui reste réellement à encaisser (reste à payer − paiements en attente de signature). */
    balance: number;
    /** Lien non payé et non expiré déjà envoyé pour cette réservation, s'il y en a un. */
    openLink: OpenPaymentLink | null;
}

/**
 * TL-297 — lien ClicToPay pour une réservation : montant pré-rempli avec le solde,
 * modifiable vers le bas pour un acompte. Une fois payé, le serveur l'enregistre
 * lui-même comme recouvrement.
 *
 * Si un lien est déjà en cours, le dialogue le propose en premier : deux liens ouverts
 * peuvent être payés tous les deux. En générer un autre demande une confirmation
 * explicite — un simple clic suffisait avant, et c'est ainsi que le doublon arrivait.
 */
export default function ClicToPayLinkDialog({ open, onOpenChange, reservationId, balance, openLink }: Props) {
    const { t } = useTranslation();
    const maxAmount = Math.max(0, Math.round(balance * 100) / 100);
    const [confirmDuplicate, setConfirmDuplicate] = useState(false);

    const { data, setData, post, processing, errors, clearErrors, transform } = useForm({
        amount: maxAmount.toFixed(2),
    });

    useEffect(() => {
        if (open) {
            setData({ amount: maxAmount.toFixed(2) });
            setConfirmDuplicate(false);
            clearErrors();
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [open, maxAmount]);

    const amount = Number(data.amount);
    const isValid = Number.isFinite(amount) && amount >= 1 && amount <= maxAmount;
    const isDeposit = isValid && amount < maxAmount;
    const blockedByOpenLink = openLink !== null && !confirmDuplicate;

    const submit = () => {
        if (blockedByOpenLink) return;
        const force = openLink !== null;
        transform((d) => ({ ...d, amount: Number(d.amount).toFixed(2), force }));
        post(route('clictopay.generate-reservation', reservationId), {
            preserveScroll: true,
            onSuccess: () => onOpenChange(false),
        });
    };

    const copyOpenLink = () => {
        if (!openLink?.form_url) return;
        navigator.clipboard.writeText(openLink.form_url);
        toast.success(t('clictopay', 'copied', 'Lien copié.'));
        onOpenChange(false);
    };

    return (
        <Dialog open={open} onOpenChange={onOpenChange}>
            <DialogContent className="sm:max-w-md">
                <DialogHeader>
                    <DialogTitle className="flex items-center gap-2">
                        <CreditCard className="h-5 w-5" /> {t('clictopay', 'reservation_link_dialog_title', 'Lien de paiement ClicToPay')}
                    </DialogTitle>
                    <DialogDescription>
                        {t(
                            'clictopay',
                            'reservation_link_auto_note',
                            'Une fois payé, le montant est enregistré automatiquement comme recouvrement de cette réservation.',
                        )}
                    </DialogDescription>
                </DialogHeader>

                {openLink && (
                    <div className="space-y-3 rounded-md border border-amber-200 bg-amber-50 p-3 text-sm text-amber-900 dark:border-amber-900 dark:bg-amber-950/30 dark:text-amber-200">
                        <div className="flex gap-2">
                            <AlertTriangle className="mt-0.5 h-4 w-4 shrink-0" />
                            <div>
                                <div className="font-medium">
                                    {t('clictopay', 'reservation_link_open_title', 'Un lien est déjà en attente de paiement')}
                                </div>
                                <div className="text-xs">
                                    {openLink.amount} TND · <span className="font-mono">{openLink.order_number}</span>
                                    {openLink.expires_at && (
                                        <>
                                            {' · '}
                                            {t('clictopay', 'expires', 'Expire le')} {openLink.expires_at}
                                        </>
                                    )}
                                </div>
                            </div>
                        </div>
                        <div className="flex flex-wrap gap-2">
                            {openLink.form_url && (
                                <Button size="sm" className="gap-1" onClick={copyOpenLink}>
                                    <Copy className="h-3.5 w-3.5" /> {t('clictopay', 'reservation_link_copy_open', 'Copier ce lien')}
                                </Button>
                            )}
                            <Button size="sm" variant="outline" asChild>
                                <Link href={route('clictopay.show', openLink.id)}>{t('clictopay', 'view', 'Voir')}</Link>
                            </Button>
                        </div>
                    </div>
                )}

                <div className="space-y-2" data-tour="clictopay-link-amount">
                    <Label htmlFor="clictopay-amount">{t('clictopay', 'amount', 'Montant (TND)')}</Label>
                    <Input
                        id="clictopay-amount"
                        type="number"
                        inputMode="decimal"
                        min={1}
                        max={maxAmount}
                        step="0.01"
                        value={data.amount}
                        disabled={blockedByOpenLink}
                        onChange={(e) => setData('amount', e.target.value)}
                    />
                    <p className="text-xs text-muted-foreground">
                        {t('clictopay', 'reservation_link_max', 'Maximum : :amount TND').replace(':amount', maxAmount.toFixed(2))}
                        {isValid && (
                            <>
                                {' — '}
                                {isDeposit
                                    ? t('clictopay', 'reservation_link_amount_hint_deposit', 'Acompte : le reste restera à encaisser.')
                                    : t('clictopay', 'reservation_link_amount_hint_full', 'Solde : le lien couvre tout le reste à payer.')}
                            </>
                        )}
                    </p>
                    <InputError message={errors.amount} />
                </div>

                {openLink && (
                    <label className="flex cursor-pointer items-start gap-2 text-sm">
                        <Checkbox
                            checked={confirmDuplicate}
                            onCheckedChange={(v) => setConfirmDuplicate(v === true)}
                            className="mt-0.5"
                        />
                        <span>
                            {t(
                                'clictopay',
                                'reservation_link_confirm_duplicate',
                                "Générer un second lien quand même — s'ils sont payés tous les deux, le voyageur paiera deux fois.",
                            )}
                        </span>
                    </label>
                )}

                <DialogFooter className="gap-2">
                    <Button variant="outline" onClick={() => onOpenChange(false)} disabled={processing}>
                        {t('clictopay', 'cancel', 'Annuler')}
                    </Button>
                    <Button
                        variant={openLink ? 'outline' : 'default'}
                        onClick={submit}
                        disabled={processing || !isValid || blockedByOpenLink}
                    >
                        {processing
                            ? t('clictopay', 'generating', 'Génération…')
                            : openLink
                              ? t('clictopay', 'reservation_link_generate_second', 'Générer un second lien')
                              : t('clictopay', 'generate', 'Générer')}
                    </Button>
                </DialogFooter>
            </DialogContent>
        </Dialog>
    );
}
