import { useState } from 'react';
import { Badge } from '@/components/ui/badge';
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 type {
    CrujiaConfigData,
    ElementoFilaData,
    ElementosTecnologicosData,
} from '@/generated/types';
import { index as elementosConstructivosIndex } from '@/routes/elementos-constructivos';
import { useCatalogo } from '../../hooks/use-catalogo';
import { useSectionForm } from '../../lib/section-form-context';
import { ElementoSelector } from './elemento-selector';
import { ElementosTable } from './elementos-table';

type ElementoCatalogo = {
    id: number;
    nombre: string;
    categoria: string;
    sort_order: number;
};

type CatalogoAgrupado = Record<string, ElementoCatalogo[]>;

export function buildPlantKeys(totalPlantas: number): string[] {
    const keys = ['pb'];
    for (let i = 1; i < totalPlantas; i++) {
        keys.push(`p${i}`);
    }
    return keys;
}

export function ElementosTecnologicos() {
    const { data, setData } = useSectionForm<ElementosTecnologicosData>();
    const { data: catalogo, loading } = useCatalogo<CatalogoAgrupado>(elementosConstructivosIndex.url());

    const [dialogOpen, setDialogOpen] = useState(false);
    const [nuevoCodigo, setNuevoCodigo] = useState('');
    const [nuevoTotalPlantas, setNuevoTotalPlantas] = useState(2);

    const selectedIds = data.filas.map((f) => f.elemento_id);

    const handleToggleElemento = (id: number, checked: boolean) => {
        if (checked) {
            const nuevaFila: ElementoFilaData = {
                elemento_id: id,
                sist_const: null,
                mat_acabados: null,
                estado_conservacion: null,
                crujias: {},
            };
            for (const c of data.crujias) {
                nuevaFila.crujias[c.codigo] = {};
                for (const pk of buildPlantKeys(c.total_plantas)) {
                    nuevaFila.crujias[c.codigo][pk] = false;
                }
            }
            setData('filas', [...data.filas, nuevaFila]);
        } else {
            setData('filas', data.filas.filter((f) => f.elemento_id !== id));
        }
    };

    const handleFilaChange = (elementoId: number, patch: Partial<ElementoFilaData>) => {
        setData('filas', data.filas.map((f) =>
            f.elemento_id === elementoId ? { ...f, ...patch } : f,
        ));
    };

    const handleCrujiaToggle = (elementoId: number, codigo: string, planta: string, value: boolean) => {
        setData('filas', data.filas.map((f) => {
            if (f.elemento_id !== elementoId) { return f; }
            return {
                ...f,
                crujias: {
                    ...f.crujias,
                    [codigo]: { ...f.crujias[codigo], [planta]: value },
                },
            };
        }));
    };

    const handleAddCrujia = () => {
        const codigo = nuevoCodigo.trim().toUpperCase();
        if (!/^[CB][1-9][0-9]?$/.test(codigo) || data.crujias.some((c) => c.codigo === codigo)) { return; }

        const nuevaCrujia: CrujiaConfigData = {
            codigo,
            total_plantas: nuevoTotalPlantas,
        };

        const plantKeys = buildPlantKeys(nuevoTotalPlantas);
        const filasActualizadas = data.filas.map((f) => ({
            ...f,
            crujias: {
                ...f.crujias,
                [codigo]: Object.fromEntries(plantKeys.map((pk) => [pk, false])),
            },
        }));

        setData({
            crujias: [...data.crujias, nuevaCrujia],
            filas: filasActualizadas,
        });

        setNuevoCodigo('');
        setNuevoTotalPlantas(2);
        setDialogOpen(false);
    };

    const handleRemoveCrujia = (codigo: string) => {
        const filasActualizadas = data.filas.map((f) => {
            const { [codigo]: _, ...rest } = f.crujias;
            return { ...f, crujias: rest };
        });
        setData({
            crujias: data.crujias.filter((c) => c.codigo !== codigo),
            filas: filasActualizadas,
        });
    };

    const catalogoSafe = catalogo ?? {};
    const catalogoFlat = Object.values(catalogoSafe).flat();

    return (
        <div className="flex gap-6">
            <div className="w-80 shrink-0">
                <ElementoSelector
                    catalogo={catalogoSafe}
                    selectedIds={selectedIds}
                    onToggle={handleToggleElemento}
                    loading={loading}
                />
            </div>

            <div className="flex-1 flex flex-col gap-4">
                <div className="flex items-center gap-2 flex-wrap">
                    <span className="text-sm font-medium text-muted-foreground">Crujías:</span>
                    {data.crujias.map((c) => (
                        <Badge key={c.codigo} variant="secondary" className="gap-1">
                            {c.codigo} · {c.total_plantas}P
                            <button
                                type="button"
                                onClick={() => handleRemoveCrujia(c.codigo)}
                                className="ml-1 text-muted-foreground hover:text-foreground"
                                aria-label={`Eliminar crujía ${c.codigo}`}
                            >
                                ✕
                            </button>
                        </Badge>
                    ))}
                    <Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
                        <DialogTrigger asChild>
                            <Button variant="outline" size="sm">+ Crujía</Button>
                        </DialogTrigger>
                        <DialogContent>
                            <DialogHeader>
                                <DialogTitle>Nueva Crujía</DialogTitle>
                                <DialogDescription>
                                    Usa códigos C o B seguidos de un número, y define el total de plantas incluyendo planta baja.
                                </DialogDescription>
                            </DialogHeader>
                            <div className="flex flex-col gap-4">
                                <div className="flex flex-col gap-2">
                                    <Label htmlFor="crujia-codigo">Código</Label>
                                    <Input
                                        id="crujia-codigo"
                                        value={nuevoCodigo}
                                        onChange={(e) => setNuevoCodigo(e.target.value.toUpperCase())}
                                        placeholder="C1 o B1"
                                        pattern="[CB][1-9][0-9]?"
                                        maxLength={3}
                                    />
                                </div>
                                <div className="flex flex-col gap-2">
                                    <Label htmlFor="crujia-plantas">Total de plantas</Label>
                                    <Input
                                        id="crujia-plantas"
                                        type="number"
                                        min={1}
                                        max={20}
                                        value={nuevoTotalPlantas}
                                        onChange={(e) => setNuevoTotalPlantas(Number(e.target.value))}
                                    />
                                </div>
                            </div>
                            <DialogFooter>
                                <Button
                                    disabled={!/^[CB][1-9][0-9]?$/.test(nuevoCodigo.trim())}
                                    onClick={handleAddCrujia}
                                >
                                    Agregar
                                </Button>
                            </DialogFooter>
                        </DialogContent>
                    </Dialog>
                </div>

                {data.filas.length > 0 ? (
                    <ElementosTable
                        filas={data.filas}
                        crujias={data.crujias}
                        catalogo={catalogoFlat}
                        onFilaChange={handleFilaChange}
                        onCrujiaToggle={handleCrujiaToggle}
                    />
                ) : (
                    <div className="flex items-center justify-center rounded-lg border border-dashed border-border p-12 text-sm text-muted-foreground">
                        Selecciona elementos del catálogo para comenzar
                    </div>
                )}
            </div>
        </div>
    );
}
