import { Plus, Upload, X } from 'lucide-react';
import { useEffect, useRef, useState, useCallback } from 'react';
import { uploadFile, UploadError, getTemporaryUrl } from '@/lib/upload';

type FileUploadMultipleItem = {
    key: string;
    url: string | null;
};

type FileUploadMultipleProps = {
    value: FileUploadMultipleItem[];
    onChange: (items: FileUploadMultipleItem[]) => void;
    maxItems?: number;
    folder?: string;
    accept?: string;
    onUploadingChange?: (uploading: boolean) => void;
};

export function FileUploadMultiple({
    value,
    onChange,
    maxItems = 5,
    folder,
    accept = 'image/jpeg,image/png,image/webp,image/gif',
    onUploadingChange,
}: FileUploadMultipleProps) {
    const inputRef = useRef<HTMLInputElement>(null);
    const [error, setError] = useState<string | null>(null);
    const [uploadingCount, setUploadingCount] = useState(0);

    const onUploadingChangeRef = useRef(onUploadingChange);

    useEffect(() => {
        onUploadingChangeRef.current = onUploadingChange;
    });

    useEffect(() => {
        onUploadingChangeRef.current?.(uploadingCount > 0);
    }, [uploadingCount]);

    const handleFileChange = useCallback(
        async (e: React.ChangeEvent<HTMLInputElement>) => {
            const file = e.target.files?.[0];

            if (!file) {
                return;
            }

            if (value.length >= maxItems) {
                setError(`Maksimal ${maxItems} gambar.`);

                return;
            }

            setError(null);
            setUploadingCount((prev) => prev + 1);

            try {
                const key = await uploadFile(file, folder);
                const newItem: FileUploadMultipleItem = {
                    key,
                    url: getTemporaryUrl(key),
                };
                onChange([...value, newItem]);
            } catch (err) {
                const message =
                    err instanceof UploadError
                        ? err.message
                        : 'Gagal mengunggah file.';
                setError(message);
            } finally {
                setUploadingCount((prev) => prev - 1);

                if (inputRef.current) {
                    inputRef.current.value = '';
                }
            }
        },
        [value, maxItems, folder, onChange],
    );

    function handleRemove(index: number) {
        const updated = value.filter((_, i) => i !== index);
        onChange(updated);
        setError(null);
    }

    const canAdd = value.length < maxItems;

    return (
        <div className="grid gap-2">
            <div className="flex flex-wrap gap-3">
                {value.map((item, index) => (
                    <div
                        key={item.key}
                        className="group relative h-24 w-24 overflow-hidden rounded-lg border bg-muted"
                    >
                        <img
                            src={item.url ?? undefined}
                            alt={`Foto ${index + 1}`}
                            className="h-full w-full object-cover"
                        />
                        {index === 0 && (
                            <span className="absolute left-1 top-1 rounded bg-primary px-1.5 py-0.5 text-[10px] font-medium text-primary-foreground">
                                Utama
                            </span>
                        )}
                        <button
                            type="button"
                            onClick={() => handleRemove(index)}
                            className="absolute right-1 top-1 rounded-full bg-black/60 p-0.5 text-white opacity-0 transition-opacity hover:bg-black/80 group-hover:opacity-100"
                        >
                            <X className="h-3 w-3" />
                        </button>
                    </div>
                ))}

                {canAdd && (
                    <button
                        type="button"
                        onClick={() => inputRef.current?.click()}
                        className="flex h-24 w-24 flex-col items-center justify-center gap-1 rounded-lg border-2 border-dashed bg-muted/50 text-muted-foreground transition-colors hover:border-primary/50 hover:bg-muted"
                    >
                        {uploadingCount > 0 ? (
                            <Upload className="h-5 w-5 animate-pulse" />
                        ) : (
                            <Plus className="h-5 w-5" />
                        )}
                        <span className="text-[10px]">
                            {uploadingCount > 0
                                ? 'Mengunggah...'
                                : 'Tambah Foto'}
                        </span>
                    </button>
                )}
            </div>

            <input
                ref={inputRef}
                type="file"
                accept={accept}
                onChange={handleFileChange}
                className="hidden"
            />

            {error && (
                <p className="text-xs text-destructive">{error}</p>
            )}

            <p className="text-xs text-muted-foreground">
                {value.length}/{maxItems} foto · Klik foto pertama sebagai
                thumbnail utama
            </p>
        </div>
    );
}
