/**
 * ImageUploader Component
 * Drag-and-drop image upload zone with preview.
 */

import { useState, useCallback, useRef } from "react";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Upload, X, Image as ImageIcon, Loader2, AlertCircle } from "lucide-react";
import { ImageCropper } from "@/components/image-cropper";

interface ImageUploaderProps {
    existingUrl?: string | null;
    onFileSelect: (file: File | null) => void;
    disabled?: boolean;
    maxSizeMB?: number;
}

const ACCEPTED_TYPES = ["image/png", "image/jpeg", "image/webp", "image/gif"];
const MAX_SIZE_DEFAULT = 15; // 15MB

export function ImageUploader({
    existingUrl,
    onFileSelect,
    disabled,
    maxSizeMB = MAX_SIZE_DEFAULT,
}: ImageUploaderProps) {
    const [previewUrl, setPreviewUrl] = useState<string | null>(existingUrl || null);
    const [isDragging, setIsDragging] = useState(false);
    const [error, setError] = useState<string | null>(null);
    const [isLoading, setIsLoading] = useState(false);

    // Cropper state
    const [isCropperOpen, setIsCropperOpen] = useState(false);
    const [tempImageSrc, setTempImageSrc] = useState<string | null>(null);
    const [tempFileName, setTempFileName] = useState<string>("image.jpg");

    const inputRef = useRef<HTMLInputElement>(null);

    const validateFile = useCallback((file: File): string | null => {
        if (!ACCEPTED_TYPES.includes(file.type)) {
            return "Invalid file type. Please use PNG, JPEG, WebP, or GIF.";
        }
        if (file.size > maxSizeMB * 1024 * 1024) {
            return `File too large. Maximum size is ${maxSizeMB}MB.`;
        }
        return null;
    }, [maxSizeMB]);

    const handleFile = useCallback((file: File) => {
        setError(null);
        const validationError = validateFile(file);

        if (validationError) {
            setError(validationError);
            return;
        }

        setIsLoading(true);
        setTempFileName(file.name);

        // Read file for cropper
        const reader = new FileReader();
        reader.onload = () => {
            setTempImageSrc(reader.result as string);
            setIsCropperOpen(true);
            setIsLoading(false);
        };
        reader.onerror = () => {
            setError("Failed to read file");
            setIsLoading(false);
        };
        reader.readAsDataURL(file);
    }, [validateFile]);

    const handleCropComplete = useCallback((croppedBlob: Blob) => {
        // Convert blob back to file
        const file = new File([croppedBlob], tempFileName, { type: "image/jpeg" });

        // Create preview
        const url = URL.createObjectURL(croppedBlob);
        setPreviewUrl(url);

        // Pass to parent
        onFileSelect(file);
        setIsCropperOpen(false);
        setTempImageSrc(null);
    }, [onFileSelect, tempFileName]);

    const handleDragEnter = useCallback((e: React.DragEvent) => {
        e.preventDefault();
        e.stopPropagation();
        if (!disabled) {
            setIsDragging(true);
        }
    }, [disabled]);

    const handleDragLeave = useCallback((e: React.DragEvent) => {
        e.preventDefault();
        e.stopPropagation();
        setIsDragging(false);
    }, []);

    const handleDragOver = useCallback((e: React.DragEvent) => {
        e.preventDefault();
        e.stopPropagation();
    }, []);

    const handleDrop = useCallback((e: React.DragEvent) => {
        e.preventDefault();
        e.stopPropagation();
        setIsDragging(false);

        if (disabled) return;

        const files = e.dataTransfer.files;
        const file = files[0];
        if (file) {
            handleFile(file);
        }
    }, [disabled, handleFile]);

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

    const handleRemove = useCallback(() => {
        setPreviewUrl(null);
        setError(null);
        onFileSelect(null);
        if (inputRef.current) {
            inputRef.current.value = "";
        }
    }, [onFileSelect]);

    const handleClick = useCallback(() => {
        if (!disabled) {
            inputRef.current?.click();
        }
    }, [disabled]);

    // Show preview state
    if (previewUrl) {
        return (
            <div className="relative">
                <div className="relative aspect-square max-w-[200px] rounded-lg overflow-hidden border border-border/50 bg-muted/30">
                    <img
                        src={previewUrl}
                        alt="Item preview"
                        className="w-full h-full object-contain"
                    />
                    {!disabled && (
                        <div className="absolute inset-0 bg-black/50 opacity-0 hover:opacity-100 transition-opacity flex items-center justify-center gap-2">
                            <Button
                                type="button"
                                variant="secondary"
                                size="sm"
                                onClick={handleClick}
                            >
                                Replace
                            </Button>
                            <Button
                                type="button"
                                variant="destructive"
                                size="sm"
                                onClick={handleRemove}
                            >
                                <X className="h-4 w-4" />
                            </Button>
                        </div>
                    )}
                </div>
                <input
                    ref={inputRef}
                    type="file"
                    accept={ACCEPTED_TYPES.join(",")}
                    onChange={handleInputChange}
                    className="hidden"
                />
            </div>
        );
    }

    // Show upload zone
    return (
        <div className="space-y-2">
            <div
                onClick={handleClick}
                onDragEnter={handleDragEnter}
                onDragLeave={handleDragLeave}
                onDragOver={handleDragOver}
                onDrop={handleDrop}
                className={cn(
                    "relative flex flex-col items-center justify-center p-8 border-2 border-dashed rounded-lg transition-colors cursor-pointer",
                    isDragging && "border-primary bg-primary/5",
                    error && "border-destructive bg-destructive/5",
                    !isDragging && !error && "border-border/50 hover:border-border bg-muted/10",
                    disabled && "opacity-50 cursor-not-allowed"
                )}
            >
                {isLoading ? (
                    <Loader2 className="h-8 w-8 text-muted-foreground animate-spin" />
                ) : error ? (
                    <AlertCircle className="h-8 w-8 text-destructive" />
                ) : (
                    <div className="flex flex-col items-center gap-2 text-center">
                        {isDragging ? (
                            <Upload className="h-8 w-8 text-primary animate-bounce" />
                        ) : (
                            <ImageIcon className="h-8 w-8 text-muted-foreground" />
                        )}
                        <div className="text-sm text-muted-foreground">
                            {isDragging ? (
                                <p className="text-primary font-medium">Drop to upload</p>
                            ) : (
                                <>
                                    <p className="font-medium">Drop image or click to browse</p>
                                    <p className="text-xs mt-1">
                                        PNG, JPEG, WebP, GIF • Max {maxSizeMB}MB
                                    </p>
                                </>
                            )}
                        </div>
                    </div>
                )}

                <input
                    ref={inputRef}
                    type="file"
                    accept={ACCEPTED_TYPES.join(",")}
                    onChange={handleInputChange}
                    className="hidden"
                    disabled={disabled}
                />
            </div>


            {error && (
                <p className="text-sm text-destructive flex items-center gap-1">
                    <AlertCircle className="h-4 w-4" />
                    {error}
                </p>
            )}

            <ImageCropper
                isOpen={isCropperOpen}
                onClose={() => setIsCropperOpen(false)}
                onCropComplete={handleCropComplete}
                imageSrc={tempImageSrc}
            />
        </div>
    );
}

export default ImageUploader;
