import { router } from '@inertiajs/react';
import { AlertCircleIcon, SparklesIcon, TrashIcon } from 'lucide-react';
import { type ReactNode, useState } from 'react';
import type {
    AiParsedParticipant,
    AiParticipantsResponse,
    ParticipantRole,
} from '@/components/classrooms/types';
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
import { Button } from '@/components/ui/button';
import {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogFooter,
    DialogHeader,
    DialogTitle,
    DialogTrigger,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { Spinner } from '@/components/ui/spinner';
import {
    Table,
    TableBody,
    TableCell,
    TableHead,
    TableHeader,
    TableRow,
} from '@/components/ui/table';
import { Textarea } from '@/components/ui/textarea';
import {
    Tooltip,
    TooltipContent,
    TooltipTrigger,
} from '@/components/ui/tooltip';
import { postJson, rowErrorMessages } from '@/lib/ai';
import classrooms from '@/routes/classrooms';

const PLACEHOLDER = `Rossi Mario RSSMRA80A01H501U mario.rossi@example.com
Bianchi Anna BNCNNA85M41F205Q anna.bianchi@example.com 3331234567
Verdi Luca, docente, luca.verdi@example.com`;

type Props = {
    classroomUuid: string;
    trigger: ReactNode;
};

export default function ParticipantAiImportDialog({
    classroomUuid,
    trigger,
}: Props) {
    const [open, setOpen] = useState(false);
    const [text, setText] = useState('');
    const [rows, setRows] = useState<AiParsedParticipant[] | null>(null);
    const [warnings, setWarnings] = useState<string[]>([]);
    const [error, setError] = useState<string | null>(null);
    const [analyzing, setAnalyzing] = useState(false);
    const [importing, setImporting] = useState(false);
    const [importErrors, setImportErrors] = useState<string[]>([]);

    function reset() {
        setText('');
        setRows(null);
        setWarnings([]);
        setError(null);
        setAnalyzing(false);
        setImporting(false);
        setImportErrors([]);
    }

    function handleOpenChange(next: boolean) {
        setOpen(next);
        if (!next) {
            reset();
        }
    }

    async function analyze() {
        setAnalyzing(true);
        setError(null);

        try {
            const data = await postJson<AiParticipantsResponse>(
                classrooms.participants.aiParse({ classroom: classroomUuid })
                    .url,
                { text },
            );

            setRows(data.rows);
            setWarnings(data.warnings);
        } catch (e) {
            setError(e instanceof Error ? e.message : 'Errore imprevisto.');
        } finally {
            setAnalyzing(false);
        }
    }

    function updateRow(
        index: number,
        field: keyof AiParsedParticipant,
        value: string,
    ) {
        setRows((current) =>
            (current ?? []).map((row, i) =>
                i === index
                    ? {
                          ...row,
                          [field]: value,
                          // Corretto a mano: tocca al server dire se ora è valido.
                          ...(field === 'fiscal_code'
                              ? { importable: true }
                              : {}),
                      }
                    : row,
            ),
        );
    }

    function removeRow(index: number) {
        setRows((current) => (current ?? []).filter((_, i) => i !== index));
    }

    function importRows() {
        if (!rows || rows.length === 0) {
            return;
        }

        setImporting(true);
        setImportErrors([]);

        router.post(
            classrooms.participants.bulk({ classroom: classroomUuid }).url,
            {
                rows: rows.map((row) => ({
                    first_name: row.first_name,
                    last_name: row.last_name,
                    fiscal_code: row.fiscal_code,
                    email: row.email,
                    phone: row.phone,
                    role: row.role,
                })),
            },
            {
                preserveScroll: true,
                onSuccess: () => handleOpenChange(false),
                onError: (errors) =>
                    setImportErrors(rowErrorMessages(errors, 'rows')),
                onFinish: () => setImporting(false),
            },
        );
    }

    return (
        <Dialog open={open} onOpenChange={handleOpenChange}>
            <DialogTrigger asChild>{trigger}</DialogTrigger>
            <DialogContent className="max-h-[90vh] gap-0 overflow-y-auto sm:max-w-4xl">
                <DialogHeader>
                    <DialogTitle>Incolla un elenco</DialogTitle>
                    <DialogDescription>
                        Incolla l&apos;elenco dei discenti come ti è arrivato,
                        da una email o da un foglio di calcolo.
                        L&apos;assistente lo trasforma in righe che puoi
                        correggere prima di importarle.
                    </DialogDescription>
                </DialogHeader>

                <div className="space-y-4 py-4">
                    {rows === null ? (
                        <div className="grid gap-2">
                            <Label htmlFor="ai-participants-text">
                                Elenco da analizzare
                            </Label>
                            <Textarea
                                id="ai-participants-text"
                                value={text}
                                onChange={(e) => setText(e.target.value)}
                                placeholder={PLACEHOLDER}
                                rows={10}
                                maxLength={20000}
                                className="font-mono text-xs"
                            />
                            <p className="text-muted-foreground text-xs">
                                Una persona per riga. Nome, cognome, codice
                                fiscale, email e telefono in qualsiasi ordine.
                            </p>
                        </div>
                    ) : (
                        <ParsedRowsTable
                            rows={rows}
                            onChange={updateRow}
                            onRemove={removeRow}
                        />
                    )}

                    {warnings.length > 0 && (
                        <Alert>
                            <AlertCircleIcon />
                            <AlertTitle>Da controllare</AlertTitle>
                            <AlertDescription>
                                {warnings.map((warning) => (
                                    <p key={warning}>{warning}</p>
                                ))}
                            </AlertDescription>
                        </Alert>
                    )}

                    {importErrors.length > 0 && (
                        <Alert variant="destructive">
                            <AlertCircleIcon />
                            <AlertTitle>
                                Correggi queste righe prima di importare
                            </AlertTitle>
                            <AlertDescription>
                                {importErrors.map((message) => (
                                    <p key={message}>{message}</p>
                                ))}
                            </AlertDescription>
                        </Alert>
                    )}

                    {error && (
                        <Alert variant="destructive">
                            <AlertCircleIcon />
                            <AlertTitle>
                                Non è stato possibile analizzare l&apos;elenco
                            </AlertTitle>
                            <AlertDescription>{error}</AlertDescription>
                        </Alert>
                    )}
                </div>

                <DialogFooter>
                    {rows !== null && (
                        <Button
                            type="button"
                            variant="ghost"
                            onClick={() => setRows(null)}
                        >
                            Modifica il testo
                        </Button>
                    )}

                    {rows === null ? (
                        <Button
                            type="button"
                            onClick={analyze}
                            disabled={analyzing || text.trim().length === 0}
                        >
                            {analyzing ? <Spinner /> : <SparklesIcon />}
                            Analizza
                        </Button>
                    ) : (
                        <Button
                            type="button"
                            onClick={importRows}
                            disabled={importing || rows.length === 0}
                        >
                            {importing && <Spinner />}
                            {rows.length === 1
                                ? 'Importa 1 partecipante'
                                : `Importa ${rows.length} partecipanti`}
                        </Button>
                    )}
                </DialogFooter>
            </DialogContent>
        </Dialog>
    );
}

function ParsedRowsTable({
    rows,
    onChange,
    onRemove,
}: {
    rows: AiParsedParticipant[];
    onChange: (
        index: number,
        field: keyof AiParsedParticipant,
        value: string,
    ) => void;
    onRemove: (index: number) => void;
}) {
    if (rows.length === 0) {
        return (
            <p className="text-muted-foreground py-6 text-center text-sm">
                Nessuna riga da importare.
            </p>
        );
    }

    return (
        <div className="rounded-xl border">
            <Table>
                <TableHeader>
                    <TableRow>
                        <TableHead className="w-[15%]">Cognome</TableHead>
                        <TableHead className="w-[15%]">Nome</TableHead>
                        <TableHead className="w-[20%]">Cod. fiscale</TableHead>
                        <TableHead className="w-[22%]">Email</TableHead>
                        <TableHead className="w-[13%]">Telefono</TableHead>
                        <TableHead className="w-[12%]">Ruolo</TableHead>
                        <TableHead className="w-[3%]" />
                    </TableRow>
                </TableHeader>
                <TableBody>
                    {rows.map((row, index) => (
                        <TableRow
                            key={index}
                            className={
                                row.importable === false
                                    ? 'bg-destructive/5'
                                    : undefined
                            }
                        >
                            <TableCell>
                                <Input
                                    aria-label={`Cognome riga ${index + 1}`}
                                    value={row.last_name}
                                    onChange={(e) =>
                                        onChange(
                                            index,
                                            'last_name',
                                            e.target.value,
                                        )
                                    }
                                />
                            </TableCell>
                            <TableCell>
                                <Input
                                    aria-label={`Nome riga ${index + 1}`}
                                    value={row.first_name}
                                    onChange={(e) =>
                                        onChange(
                                            index,
                                            'first_name',
                                            e.target.value,
                                        )
                                    }
                                />
                            </TableCell>
                            <TableCell>
                                <div className="flex items-center gap-1">
                                    <Input
                                        aria-label={`Codice fiscale riga ${index + 1}`}
                                        value={row.fiscal_code ?? ''}
                                        onChange={(e) =>
                                            onChange(
                                                index,
                                                'fiscal_code',
                                                e.target.value.toUpperCase(),
                                            )
                                        }
                                        className="font-mono text-xs uppercase"
                                    />
                                    {row.warnings.length > 0 && (
                                        <Tooltip>
                                            <TooltipTrigger asChild>
                                                <AlertCircleIcon className="text-muted-foreground size-4 shrink-0" />
                                            </TooltipTrigger>
                                            <TooltipContent>
                                                {row.warnings.map((warning) => (
                                                    <p key={warning}>
                                                        {warning}
                                                    </p>
                                                ))}
                                            </TooltipContent>
                                        </Tooltip>
                                    )}
                                </div>
                                {row.importable === false ? (
                                    <p className="text-destructive mt-1 text-xs">
                                        Non importabile: correggi il codice
                                        fiscale.
                                    </p>
                                ) : (
                                    row.birth_date && (
                                        <p className="text-muted-foreground mt-1 text-xs">
                                            {row.birth_date} · {row.gender} ·{' '}
                                            {row.birth_place_code}
                                        </p>
                                    )
                                )}
                            </TableCell>
                            <TableCell>
                                <Input
                                    aria-label={`Email riga ${index + 1}`}
                                    type="email"
                                    value={row.email ?? ''}
                                    onChange={(e) =>
                                        onChange(index, 'email', e.target.value)
                                    }
                                />
                            </TableCell>
                            <TableCell>
                                <Input
                                    aria-label={`Telefono riga ${index + 1}`}
                                    value={row.phone ?? ''}
                                    onChange={(e) =>
                                        onChange(index, 'phone', e.target.value)
                                    }
                                />
                            </TableCell>
                            <TableCell>
                                <Select
                                    value={row.role}
                                    onValueChange={(value) =>
                                        onChange(
                                            index,
                                            'role',
                                            value as ParticipantRole,
                                        )
                                    }
                                >
                                    <SelectTrigger
                                        aria-label={`Ruolo riga ${index + 1}`}
                                    >
                                        <SelectValue />
                                    </SelectTrigger>
                                    <SelectContent>
                                        <SelectItem value="learner">
                                            Discente
                                        </SelectItem>
                                        <SelectItem value="trainer">
                                            Docente
                                        </SelectItem>
                                    </SelectContent>
                                </Select>
                            </TableCell>
                            <TableCell>
                                <Button
                                    type="button"
                                    variant="ghost"
                                    size="icon"
                                    aria-label={`Rimuovi riga ${index + 1}`}
                                    onClick={() => onRemove(index)}
                                >
                                    <TrashIcon />
                                </Button>
                            </TableCell>
                        </TableRow>
                    ))}
                </TableBody>
            </Table>
        </div>
    );
}
