import { useEffect } from 'react';
import { show as mediaShowRoute } from '@/actions/Modules/FichaInventario/Http/Controllers/MediaController';
import { MediaGallery } from '@/components/media/MediaGallery';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import {
    Field,
    FieldDescription,
    FieldGroup,
    FieldLabel,
} from '@/components/ui/field';
import { Input } from '@/components/ui/input';
import type {
    AreaPorNivelData,
    FrenteMedidaData,
    PlantasArquitectonicasData,
} from '@/generated/types';
import { useSectionForm } from '../../lib/section-form-context';
import type { SeccionProps } from '../index';
import { AreasNivelTable } from './areas-nivel-table';
import { FrentesTable } from './frentes-table';

function toNumber(value: string): number | null {
    return value === '' ? null : Number(value);
}

function defaultNivel(index: number): string {
    if (index === 0) {
        return 'PB';
    }

    if (index === 1) {
        return 'PA';
    }

    return `P${index}`;
}

function resizeFrentes(
    current: FrenteMedidaData[],
    count: number | null,
): FrenteMedidaData[] {
    const total = Math.max(0, count ?? 0);

    return Array.from({ length: total }, (_, index) => ({
        frente: current[index]?.frente ?? index + 1,
        medida_m: current[index]?.medida_m ?? null,
    }));
}

function resizeNiveles(
    current: AreaPorNivelData[],
    count: number | null,
): AreaPorNivelData[] {
    const total = Math.max(0, count ?? 0);

    return Array.from({ length: total }, (_, index) => ({
        nivel: current[index]?.nivel ?? defaultNivel(index),
        area_m2: current[index]?.area_m2 ?? null,
    }));
}

export function PlantasArquitectonicas({ fichaId }: SeccionProps) {
    const { data, setData } = useSectionForm<PlantasArquitectonicasData>();
    const frentesMedidas = data.frentes_medidas ?? [];
    const areasConstruidasPorNivel = data.areas_construidas_por_nivel ?? [];
    const imagenes = data.imagenes ?? [];

    const areaOcupada =
        data.area_lote_m2 != null || data.area_libre_m2 != null
            ? (data.area_lote_m2 ?? 0) - (data.area_libre_m2 ?? 0)
            : null;
    const areaConstruidaTotal = areasConstruidasPorNivel.reduce(
        (sum, nivel) => sum + (nivel.area_m2 ?? 0),
        0,
    );

    useEffect(() => {
        if (data.area_ocupada_m2 !== areaOcupada) {
            setData('area_ocupada_m2', areaOcupada);
        }
    }, [areaOcupada, data.area_ocupada_m2, setData]);

    useEffect(() => {
        if (data.area_construida_total_m2 !== areaConstruidaTotal) {
            setData('area_construida_total_m2', areaConstruidaTotal);
        }
    }, [areaConstruidaTotal, data.area_construida_total_m2, setData]);

    return (
        <div className="flex flex-col gap-6">
            <Card>
                <CardHeader>
                    <CardTitle>Datos Generales</CardTitle>
                </CardHeader>
                <CardContent>
                    <FieldGroup className="grid gap-4 md:grid-cols-2">
                        <NumberField
                            label="N° de niveles"
                            value={data.numero_niveles_plantas}
                            onChange={(value) => {
                                setData((current) => ({
                                    ...current,
                                    numero_niveles_plantas: value,
                                    areas_construidas_por_nivel: resizeNiveles(
                                        current.areas_construidas_por_nivel ?? [],
                                        value,
                                    ),
                                }));
                            }}
                        />
                        <NumberField
                            label="N° de frentes"
                            value={data.numero_frentes}
                            onChange={(value) => {
                                setData((current) => ({
                                    ...current,
                                    numero_frentes: value,
                                    frentes_medidas: resizeFrentes(
                                        current.frentes_medidas ?? [],
                                        value,
                                    ),
                                }));
                            }}
                        />
                        <NumberField
                            label="Área de lote (m²)"
                            value={data.area_lote_m2}
                            step="0.01"
                            onChange={(value) => setData('area_lote_m2', value)}
                        />
                        <NumberField
                            label="Área libre (m²)"
                            value={data.area_libre_m2}
                            step="0.01"
                            onChange={(value) => setData('area_libre_m2', value)}
                        />
                        <NumberField
                            label="Área ocupada (m²)"
                            value={areaOcupada}
                            step="0.01"
                            readOnly
                            onChange={() => undefined}
                        />
                        <NumberField
                            label="Área construida total (m²)"
                            value={areaConstruidaTotal}
                            step="0.01"
                            readOnly
                            onChange={() => undefined}
                        />
                    </FieldGroup>
                </CardContent>
            </Card>

            <Card>
                <CardHeader>
                    <CardTitle>Frentes y Medidas</CardTitle>
                </CardHeader>
                <CardContent className="flex flex-col gap-3">
                    <FieldDescription>
                        Las filas se generan según el número de frentes.
                    </FieldDescription>
                    <FrentesTable
                        value={frentesMedidas}
                        onChange={(value) => setData('frentes_medidas', value)}
                    />
                </CardContent>
            </Card>

            <Card>
                <CardHeader>
                    <CardTitle>Áreas Construidas por Nivel</CardTitle>
                </CardHeader>
                <CardContent className="flex flex-col gap-3">
                    <FieldDescription>
                        Las filas se generan según el número de niveles.
                    </FieldDescription>
                    <AreasNivelTable
                        value={areasConstruidasPorNivel}
                        onChange={(value) =>
                            setData('areas_construidas_por_nivel', value)
                        }
                    />
                </CardContent>
            </Card>

            <Field>
                <FieldLabel>
                    Planos de Plantas Arquitectónicas
                    <span className="ml-0.5 text-destructive">*</span>
                </FieldLabel>
                <MediaGallery
                    fichaId={fichaId}
                    collection="planta_arquitectonica"
                    label="planos de plantas arquitectónicas"
                    value={imagenes
                        .filter((image) => image.id)
                        .map((image) => ({
                            id: image.id as string,
                            previewUrl: mediaShowRoute.url({
                                media: image.id as string,
                            }),
                            mimeType: 'image/jpeg',
                        }))}
                    minItems={1}
                    onChange={(items) =>
                        setData(
                            'imagenes',
                            items.map((item) => ({
                                id: item.id,
                            })),
                        )
                    }
                />
            </Field>
        </div>
    );
}

interface NumberFieldProps {
    label: string;
    value: number | null;
    onChange: (value: number | null) => void;
    step?: string;
    readOnly?: boolean;
}

function NumberField({
    label,
    value,
    onChange,
    step,
    readOnly,
}: NumberFieldProps) {
    return (
        <Field>
            <FieldLabel>{label}</FieldLabel>
            <Input
                type="number"
                step={step}
                value={value ?? ''}
                readOnly={readOnly}
                className="read-only:cursor-default read-only:bg-muted"
                onChange={(e) => onChange(toNumber(e.target.value))}
            />
        </Field>
    );
}
