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 { Progress } from '@/components/ui/progress';
import { cn } from '@/lib/utils';
import { MediaPreview } from './MediaPreview';
import { useMediaUpload } from './use-media';

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

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 MediaUploader({
    fichaId,
    collection,
    value,
    onChange,
    previewUrl,
    previewMimeType = 'image/jpeg',
    label = 'Imagen',
}: MediaUploaderProps) {
    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) => {
            upload(file, (media) => {
                setLocalPreview({ url: media.preview_url, mime: media.mime_type });
                onChange({ id: media.id });
            });
        },
        [upload, onChange],
    );

    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();
    };

    if (value?.id && localPreview) {
        return (
            <div className="flex flex-col gap-3">
                <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}
                />
            </div>
        );
    }

    return (
        <div className="flex flex-col gap-3">
            <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>}
        </div>
    );
}
