import { ImagePlus, RotateCcw, Trash2 } from 'lucide-react';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useDropzone } from 'react-dropzone';
import { Button } from '@/components/ui/button';
import { Field, FieldGroup, FieldLabel } from '@/components/ui/field';
import { Input } from '@/components/ui/input';
import { Progress } from '@/components/ui/progress';
import { Textarea } from '@/components/ui/textarea';
import { cn } from '@/lib/utils';
import { MediaPreview } from './MediaPreview';
import { useMediaUpload } from './use-media';

interface ImageMetadata {
    caption: string;
    fuente: string;
    fecha_toma: string;
    hora: string;
    codificacion: string;
}

interface MediaUploaderWithMetadataProps {
    fichaId: number;
    collection: string;
    value: { id: string; metadata: ImageMetadata } | null;
    onChange: (value: { id: string; metadata: ImageMetadata } | null) => void;
    previewUrl?: string;
    previewMimeType?: string;
    label?: string;
}

const EMPTY_METADATA: ImageMetadata = {
    caption: '',
    fuente: 'UATF',
    fecha_toma: '',
    hora: '',
    codificacion: '',
};

const ACCEPT_TYPES = {
    'image/jpeg': ['.jpg', '.jpeg'],
    'image/png': ['.png'],
    'image/webp': ['.webp'],
    'application/pdf': ['.pdf'],
} as const;

const ACCEPT_STRING = 'image/jpeg,image/png,image/webp,application/pdf';

export function MediaUploaderWithMetadata({
    fichaId,
    collection,
    value,
    onChange,
    previewUrl,
    previewMimeType = 'image/jpeg',
    label = 'Imagen',
}: MediaUploaderWithMetadataProps) {
    const { upload, status, progress, error, reset } = useMediaUpload(fichaId, collection);

    const [localPreview, setLocalPreview] = useState<{ url: string; mime: string } | null>(null);
    const fileInputRef = useRef<HTMLInputElement>(null);

    useEffect(() => {
        if (value?.id && previewUrl) {
            setLocalPreview({ url: previewUrl, mime: previewMimeType });
        } else if (!value?.id) {
            setLocalPreview(null);
        }
    }, [value?.id, previewUrl, previewMimeType]);

    const handleFile = useCallback(
        (file: File) => {
            const currentMetadata = value?.metadata ?? { ...EMPTY_METADATA };
            upload(file, (media) => {
                setLocalPreview({ url: media.preview_url, mime: media.mime_type });
                onChange({ id: media.id, metadata: currentMetadata });
            });
        },
        [upload, onChange, value?.metadata],
    );

    const onDrop = useCallback(
        (acceptedFiles: File[]) => {
            const file = acceptedFiles[0];
            if (file) {
                handleFile(file);
            }
        },
        [handleFile],
    );

    const { getRootProps, getInputProps, isDragActive } = useDropzone({
        onDrop,
        accept: ACCEPT_TYPES,
        maxFiles: 1,
        multiple: false,
        disabled: !!value?.id,
    });

    const handleReplaceClick = () => {
        fileInputRef.current?.click();
    };

    const handleReplaceFile = (e: React.ChangeEvent<HTMLInputElement>) => {
        const file = e.target.files?.[0];
        if (file) {
            handleFile(file);
        }
        e.target.value = '';
    };

    const handleRemove = () => {
        setLocalPreview(null);
        onChange(null);
        reset();
    };

    const updateMetadata = (field: keyof ImageMetadata, fieldValue: string) => {
        if (!value) {
            return;
        }
        onChange({ ...value, metadata: { ...value.metadata, [field]: fieldValue } });
    };

    if (value?.id && localPreview) {
        return (
            <FieldGroup>
                <div className="group relative aspect-video overflow-hidden rounded-lg border bg-muted/30">
                    <MediaPreview
                        src={localPreview.url}
                        mimeType={localPreview.mime}
                        alt={label}
                    />
                    <div className="absolute inset-0 flex items-center justify-center bg-black/60 opacity-0 transition-opacity group-hover:opacity-100 [@media(hover:none)]:opacity-100">
                        <div className="flex items-center gap-3">
                            <Button
                                type="button"
                                variant="outline"
                                className="bg-black text-white hover:bg-black/80 hover:text-white"
                                onClick={handleReplaceClick}
                                disabled={status === 'uploading'}
                            >
                                <RotateCcw data-icon="inline-start" />
                                Reemplazar
                            </Button>
                            <Button
                                type="button"
                                variant="destructive"
                                onClick={handleRemove}
                                disabled={status === 'uploading'}
                            >
                                <Trash2 data-icon="inline-start" />
                                Quitar
                            </Button>
                        </div>
                    </div>
                </div>

                {status === 'uploading' && <Progress value={progress} />}

                {error && <p className="text-sm text-destructive">{error}</p>}

                <input
                    ref={fileInputRef}
                    type="file"
                    className="hidden"
                    accept={ACCEPT_STRING}
                    onChange={handleReplaceFile}
                />

                <Field>
                    <FieldLabel htmlFor="caption">Descripción</FieldLabel>
                    <Textarea
                        id="caption"
                        value={value.metadata.caption}
                        onChange={(e) => updateMetadata('caption', e.target.value)}
                    />
                </Field>

                <div className="grid grid-cols-2 gap-4">
                    <Field>
                        <FieldLabel htmlFor="fuente">Fuente</FieldLabel>
                        <Input
                            id="fuente"
                            readOnly
                            value={value.metadata.fuente}
                        />
                    </Field>
                    <Field>
                        <FieldLabel htmlFor="codificacion">Codificación</FieldLabel>
                        <Input
                            id="codificacion"
                            value={value.metadata.codificacion}
                            onChange={(e) => updateMetadata('codificacion', e.target.value)}
                        />
                    </Field>
                    <Field>
                        <FieldLabel htmlFor="fecha_toma">Fecha de toma</FieldLabel>
                        <Input
                            id="fecha_toma"
                            type="date"
                            value={value.metadata.fecha_toma}
                            onChange={(e) => updateMetadata('fecha_toma', e.target.value)}
                        />
                    </Field>
                    <Field>
                        <FieldLabel htmlFor="hora">Hora</FieldLabel>
                        <Input
                            id="hora"
                            type="time"
                            step={60}
                            value={value.metadata.hora}
                            onChange={(e) => updateMetadata('hora', e.target.value)}
                        />
                    </Field>
                </div>
            </FieldGroup>
        );
    }

    return (
        <FieldGroup>
            <div
                {...getRootProps()}
                className={cn(
                    'flex aspect-video cursor-pointer flex-col items-center justify-center gap-2 rounded-lg border border-dashed bg-muted/30 transition-colors',
                    isDragActive && 'border-primary/60 bg-primary/5',
                )}
            >
                <input {...getInputProps()} />
                <ImagePlus className="size-10 text-muted-foreground" />
                <p className="text-sm text-muted-foreground">
                    {isDragActive ? 'Suelta el archivo aquí' : `Arrastra o click para subir ${label.toLowerCase()}`}
                </p>
                <p className="text-xs text-muted-foreground">JPG, PNG, WebP o PDF (máx. 10MB)</p>
            </div>

            {status === 'uploading' && <Progress value={progress} />}

            {error && <p className="text-sm text-destructive">{error}</p>}
        </FieldGroup>
    );
}
