import { Button } from '@/components/ui/button';
import {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogFooter,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { router } from '@inertiajs/react';
import axios from 'axios';
import { CheckCircle2, ExternalLink, Loader2 } from 'lucide-react';
import * as React from 'react';
import { toast } from 'sonner';
import type { LedgerSource } from './types';

interface FieldValue {
    value: string;
    href?: string | null;
}

interface AllocationWorkflow {
    id: number;
    status: 'awaiting_signature' | 'pending' | 'reported' | 'approved' | 'closed' | 'rejected';
    amount_allocated: number;
    amount_used: number | null;
    remaining: number;
    report_note: string | null;
    facture_url: string | null;
    can_report: boolean;
    can_approve: boolean;
    can_confirm_return: boolean;
}

interface SourceDetailResponse {
    type: 'recovery' | 'expense' | 'receipt' | 'allocation';
    id: number;
    fields: Record<string, FieldValue | null>;
    sourceUrl: string | null;
    sourceLabel: string | null;
    allocation?: AllocationWorkflow | null;
}

interface Props {
    open: boolean;
    onOpenChange: (v: boolean) => void;
    source: LedgerSource;
    sourceId: number | null;
}

const TITLE: Record<Exclude<LedgerSource, 'manual'>, string> = {
    recovery: 'Détail du recouvrement',
    expense: 'Détail de la dépense',
    receipt: 'Détail du reçu',
    allocation: 'Détail de l’allocation',
};

export function SourceDetailDialog({ open, onOpenChange, source, sourceId }: Props) {
    const [data, setData] = React.useState<SourceDetailResponse | null>(null);
    const [loading, setLoading] = React.useState(false);

    // y-side report form state
    const [amountUsed, setAmountUsed] = React.useState('');
    const [reportNote, setReportNote] = React.useState('');
    const [factureFile, setFactureFile] = React.useState<File | null>(null);
    const [submitting, setSubmitting] = React.useState(false);

    const load = React.useCallback(() => {
        if (source === 'manual' || sourceId == null) return;
        setLoading(true);
        setData(null);
        axios
            .get<SourceDetailResponse>(`/fond-de-caisse/source/${source}/${sourceId}`)
            .then((res) => setData(res.data))
            .catch((e) => {
                toast.error(e?.response?.data?.message ?? 'Erreur de chargement');
                onOpenChange(false);
            })
            .finally(() => setLoading(false));
    }, [source, sourceId, onOpenChange]);

    React.useEffect(() => {
        if (!open) return;
        setAmountUsed('');
        setReportNote('');
        setFactureFile(null);
        load();
    }, [open, load]);

    const alloc = data?.allocation ?? null;

    const submitReport = () => {
        if (!alloc || submitting) return;
        const used = parseFloat(amountUsed);
        if (isNaN(used) || used < 0) {
            toast.error('Saisissez le montant utilisé');
            return;
        }
        if (used > alloc.amount_allocated + 0.009) {
            toast.error(`Le montant utilisé ne peut pas dépasser ${alloc.amount_allocated.toFixed(2)} TND`);
            return;
        }
        const payload: Record<string, unknown> = { amount_used: used };
        if (reportNote.trim()) payload.report_note = reportNote.trim();
        if (factureFile) payload.facture = factureFile;

        setSubmitting(true);
        router.post(route('fond-de-caisse.allocation.report', { id: alloc.id }), payload, {
            preserveScroll: true,
            forceFormData: true,
            only: ['rows', 'summary', 'flash'],
            onSuccess: () => onOpenChange(false),
            onError: (errs) => {
                const first = Object.values(errs as Record<string, string>)[0];
                toast.error(typeof first === 'string' ? first : 'Erreur lors de la déclaration');
            },
            onFinish: () => setSubmitting(false),
        });
    };

    const submitApprove = () => {
        if (!alloc || submitting) return;
        setSubmitting(true);
        router.post(route('fond-de-caisse.allocation.approve', { id: alloc.id }), {}, {
            preserveScroll: true,
            only: ['rows', 'summary', 'flash'],
            onSuccess: () => onOpenChange(false),
            onError: (errs) => {
                const first = Object.values(errs as Record<string, string>)[0];
                toast.error(typeof first === 'string' ? first : "Erreur lors de l'approbation");
            },
            onFinish: () => setSubmitting(false),
        });
    };

    const submitReturn = () => {
        if (!alloc || submitting) return;
        setSubmitting(true);
        router.post(route('fond-de-caisse.allocation.return', { id: alloc.id }), {}, {
            preserveScroll: true,
            only: ['rows', 'summary', 'flash'],
            onSuccess: () => onOpenChange(false),
            onError: (errs) => {
                const first = Object.values(errs as Record<string, string>)[0];
                toast.error(typeof first === 'string' ? first : 'Erreur lors de la confirmation du retour');
            },
            onFinish: () => setSubmitting(false),
        });
    };

    const title = source !== 'manual' ? TITLE[source] : 'Détail';

    const primaryAction = alloc?.can_report || alloc?.can_approve || alloc?.can_confirm_return;

    return (
        <Dialog open={open} onOpenChange={onOpenChange}>
            <DialogContent className="flex max-h-[90vh] flex-col gap-0 p-0 sm:max-w-lg">
                <DialogHeader className="border-b px-6 pt-6 pb-4">
                    <DialogTitle>{title}{sourceId != null && ` #${sourceId}`}</DialogTitle>
                    <DialogDescription>
                        {alloc
                            ? "Suivi de la dépense entre la finance et l'opérationnel."
                            : 'Cette ligne est synchronisée depuis sa source. Pour la modifier, ouvrez la page source.'}
                    </DialogDescription>
                </DialogHeader>

                <div className="overflow-y-auto px-6 py-4">
                {loading && (
                    <div className="text-muted-foreground flex items-center gap-2 py-6 text-sm">
                        <Loader2 className="h-4 w-4 animate-spin" />
                        Chargement…
                    </div>
                )}

                {!loading && data && (
                    <div className="grid gap-0">
                        {/* Field list — clean two-column key/value rows */}
                        <dl className="divide-y rounded-lg border">
                            {Object.entries(data.fields)
                                .filter(([, v]) => v !== null && v?.value !== '' && v !== undefined)
                                .map(([label, field]) => (
                                    <div key={label} className="flex items-start justify-between gap-4 px-3 py-2.5">
                                        <dt className="text-muted-foreground shrink-0 text-xs font-medium uppercase tracking-wide">
                                            {label}
                                        </dt>
                                        <dd className="text-right text-sm break-words">{renderField(field!)}</dd>
                                    </div>
                                ))}
                        </dl>

                        {/* Inline links — receipt + declared facture */}
                        {(data.sourceUrl || alloc?.facture_url) && (
                            <div className="mt-3 flex flex-wrap gap-x-4 gap-y-1.5">
                                {data.sourceUrl && (
                                    <a
                                        href={data.sourceUrl}
                                        target="_blank"
                                        rel="noopener noreferrer"
                                        className="text-sky-700 inline-flex items-center gap-1 text-xs underline hover:text-sky-900"
                                    >
                                        {data.sourceLabel ?? 'Ouvrir la source'} <ExternalLink className="h-3 w-3" />
                                    </a>
                                )}
                                {alloc?.facture_url && (
                                    <a
                                        href={alloc.facture_url}
                                        target="_blank"
                                        rel="noopener noreferrer"
                                        className="text-sky-700 inline-flex items-center gap-1 text-xs underline hover:text-sky-900"
                                    >
                                        Voir la facture déclarée <ExternalLink className="h-3 w-3" />
                                    </a>
                                )}
                            </div>
                        )}

                        {/* ── y-side: Traiter (report) form ─────────────────── */}
                        {alloc?.can_report && (
                            <div className="border-emerald-300 bg-emerald-50/70 mt-4 grid gap-3 rounded-lg border p-4">
                                <div className="text-emerald-900 text-sm font-semibold">
                                    Déclarer la dépense
                                </div>
                                <p className="text-emerald-800/80 text-xs leading-relaxed">
                                    Indiquez combien vous avez réellement dépensé sur les{' '}
                                    {alloc.amount_allocated.toLocaleString('fr-TN', { minimumFractionDigits: 2 })} TND reçus.
                                    Le reste demeure dans votre solde.
                                </p>
                                <div className="grid gap-1.5">
                                    <Label className="text-xs">Montant utilisé (TND)</Label>
                                    <Input
                                        type="number"
                                        step="0.01"
                                        min="0"
                                        max={alloc.amount_allocated}
                                        value={amountUsed}
                                        onChange={(e) => setAmountUsed(e.target.value)}
                                        placeholder="0.00"
                                        className="h-11 bg-white text-right text-base font-semibold tabular-nums"
                                    />
                                    {amountUsed !== '' && !isNaN(parseFloat(amountUsed)) && (
                                        <p className="text-emerald-800 text-xs font-medium">
                                            Restant dans votre solde :{' '}
                                            {(alloc.amount_allocated - parseFloat(amountUsed)).toLocaleString('fr-TN', { minimumFractionDigits: 2 })} TND
                                        </p>
                                    )}
                                </div>
                                <div className="grid gap-1.5">
                                    <Label className="text-xs">Facture / justificatif <span className="text-muted-foreground/70">(optionnel)</span></Label>
                                    <input
                                        type="file"
                                        accept="image/*,.pdf"
                                        onChange={(e) => setFactureFile(e.target.files?.[0] ?? null)}
                                        className="block w-full rounded-md border border-emerald-200 bg-white text-xs file:mr-2 file:border-0 file:border-r file:border-emerald-200 file:bg-emerald-100 file:px-3 file:py-2 file:text-xs file:font-medium file:text-emerald-800"
                                    />
                                </div>
                                <div className="grid gap-1.5">
                                    <Label className="text-xs">Note <span className="text-muted-foreground/70">(optionnel)</span></Label>
                                    <Input
                                        value={reportNote}
                                        onChange={(e) => setReportNote(e.target.value)}
                                        placeholder="Ex : achat pièces + main d'œuvre"
                                        className="h-10 bg-white"
                                    />
                                </div>
                            </div>
                        )}

                        {/* ── z-side: approval banner ───────────────────────── */}
                        {alloc?.can_approve && (
                            <div className="border-amber-300 bg-amber-50 text-amber-900 mt-4 rounded-lg border p-4 text-sm">
                                <div className="font-semibold">Déclaration à approuver</div>
                                <p className="text-amber-800/90 mt-1 text-xs leading-relaxed">
                                    Le bénéficiaire a déclaré avoir utilisé{' '}
                                    <strong>{(alloc.amount_used ?? 0).toLocaleString('fr-TN', { minimumFractionDigits: 2 })} TND</strong>{' '}
                                    — restant <strong>{alloc.remaining.toLocaleString('fr-TN', { minimumFractionDigits: 2 })} TND</strong>.
                                    {alloc.report_note ? ` Note : ${alloc.report_note}` : ''}
                                    <br />
                                    En approuvant, la dépense de {(alloc.amount_used ?? 0).toLocaleString('fr-TN', { minimumFractionDigits: 2 })} TND
                                    sera enregistrée.
                                </p>
                            </div>
                        )}

                        {/* ── z-side: confirm-return banner ─────────────────── */}
                        {alloc?.can_confirm_return && (
                            <div className="border-sky-300 bg-sky-50 text-sky-900 mt-4 rounded-lg border p-4 text-sm">
                                <div className="font-semibold">Retour du restant</div>
                                <p className="text-sky-800/90 mt-1 text-xs leading-relaxed">
                                    Le bénéficiaire doit vous rendre{' '}
                                    <strong>{alloc.remaining.toLocaleString('fr-TN', { minimumFractionDigits: 2 })} TND</strong>.
                                    Confirmez une fois l'argent en main : un reçu de retour sera créé et
                                    le montant encaissé dans votre caisse.
                                </p>
                            </div>
                        )}
                    </div>
                )}
                </div>

                <DialogFooter className="border-t px-6 py-4 sm:justify-between">
                    <Button variant="ghost" onClick={() => onOpenChange(false)} disabled={submitting}>
                        Fermer
                    </Button>
                    {alloc?.can_report && (
                        <Button onClick={submitReport} disabled={submitting} className="bg-emerald-700 text-white hover:bg-emerald-800">
                            {submitting ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : <CheckCircle2 className="mr-2 h-4 w-4" />}
                            Déclarer la dépense
                        </Button>
                    )}
                    {alloc?.can_approve && (
                        <Button onClick={submitApprove} disabled={submitting} className="bg-emerald-700 text-white hover:bg-emerald-800">
                            {submitting ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : <CheckCircle2 className="mr-2 h-4 w-4" />}
                            Approuver
                        </Button>
                    )}
                    {alloc?.can_confirm_return && (
                        <Button onClick={submitReturn} disabled={submitting} className="bg-sky-700 text-white hover:bg-sky-800">
                            {submitting ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : <CheckCircle2 className="mr-2 h-4 w-4" />}
                            Confirmer le retour ({alloc.remaining.toLocaleString('fr-TN', { minimumFractionDigits: 2 })} TND)
                        </Button>
                    )}
                    {!primaryAction && data && data.sourceUrl && (
                        <Button asChild>
                            <a href={data.sourceUrl} target="_blank" rel="noopener noreferrer">
                                <ExternalLink className="mr-2 h-4 w-4" />
                                {data.sourceLabel ?? 'Ouvrir'}
                            </a>
                        </Button>
                    )}
                </DialogFooter>
            </DialogContent>
        </Dialog>
    );
}

function renderField(field: FieldValue): React.ReactNode {
    if (!field) return '—';
    if (field.href) {
        return (
            <a
                href={field.href}
                target="_blank"
                rel="noopener noreferrer"
                className="text-sky-700 inline-flex items-center gap-1 underline hover:text-sky-900"
            >
                {field.value}
                <ExternalLink className="h-3 w-3" />
            </a>
        );
    }
    return field.value;
}
