import { useRef, useState } from 'react';
import { Label } from '@/components/ui/label';
import { cn } from '@/lib/utils';

// ─── Types ────────────────────────────────────────────────────────────────────

interface ImageUploadProps {
    label?: string;

    /** New file the user picked — pass `form.data.image` */
    value?: File | null;

    /** Called when user picks / clears a new file */
    onChange: (file: File | null) => void;

    /**
     * Existing image URL from the database (edit mode only).
     * Pass `product.image_url` (or undefined on create).
     */
    existingImageUrl?: string | null;

    /**
     * Called when the user removes the existing DB image.
     * Use this to set a `delete_image: true` flag in your form.
     * Only fires when there is an existingImageUrl and no new file selected.
     */
    onRemoveExisting?: () => void;

    accept?: string;
    maxSize?: number;
    disabled?: boolean;
    className?: string;
}

// ─── Helpers ──────────────────────────────────────────────────────────────────

const DEFAULT_MAX_SIZE = 5 * 1024 * 1024;

function formatBytes(bytes: number): string {
    if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`;
    return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
}

function getFileType(file: File): string {
    return file.type.split('/')[1]?.toUpperCase() ?? 'IMAGE';
}

// ─── Icons ────────────────────────────────────────────────────────────────────

function UploadIcon({ className }: { className?: string }) {
    return (
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
            stroke="currentColor" strokeWidth={1.5} strokeLinecap="round"
            strokeLinejoin="round" className={className} aria-hidden="true">
            <path stroke="none" d="M0 0h24v24H0z" fill="none" />
            <path d="M7 18a4.6 4.4 0 0 1 0 -9a5 4.5 0 0 1 11 2h1a3.5 3.5 0 0 1 0 7h-1" />
            <path d="M9 15l3 -3l3 3" /><path d="M12 12l0 9" />
        </svg>
    );
}

function RefreshIcon({ className }: { className?: string }) {
    return (
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
            stroke="currentColor" strokeWidth={1.5} strokeLinecap="round"
            strokeLinejoin="round" className={className} aria-hidden="true">
            <path stroke="none" d="M0 0h24v24H0z" fill="none" />
            <path d="M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4" />
            <path d="M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4" />
        </svg>
    );
}

function TrashIcon({ className }: { className?: string }) {
    return (
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
            stroke="currentColor" strokeWidth={1.5} strokeLinecap="round"
            strokeLinejoin="round" className={className} aria-hidden="true">
            <path stroke="none" d="M0 0h24v24H0z" fill="none" />
            <path d="M4 7l16 0" /><path d="M10 11l0 6" /><path d="M14 11l0 6" />
            <path d="M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2l1 -12" />
            <path d="M9 7v-3a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v3" />
        </svg>
    );
}

function AlertIcon({ className }: { className?: string }) {
    return (
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
            stroke="currentColor" strokeWidth={1.5} strokeLinecap="round"
            strokeLinejoin="round" className={className} aria-hidden="true">
            <path stroke="none" d="M0 0h24v24H0z" fill="none" />
            <path d="M12 9v4" />
            <path d="M10.363 3.591l-8.106 13.534a1.914 1.914 0 0 0 1.636 2.871h16.214a1.914 1.914 0 0 0 1.636 -2.871l-8.106 -13.534a1.914 1.914 0 0 0 -3.274 0z" />
            <path d="M12 16h.01" />
        </svg>
    );
}

// ─── Component ────────────────────────────────────────────────────────────────

export default function ImageUpload({
    label,
    value,
    onChange,
    existingImageUrl,
    onRemoveExisting,
    accept = 'image/*',
    maxSize = DEFAULT_MAX_SIZE,
    disabled = false,
    className,
}: ImageUploadProps) {
    const inputRef = useRef<HTMLInputElement>(null);
    const replaceRef = useRef<HTMLInputElement>(null);

    const [objectUrl, setObjectUrl] = useState<string | null>(null);
    const [error, setError] = useState<string | null>(null);
    const [isDragging, setIsDragging] = useState(false);

    // What to show in the thumbnail:
    //   1. Fresh object URL  (user just picked a new file)
    //   2. Existing DB image (edit mode, no new file yet)
    //   3. null              (create mode, or existing was removed)
    const preview = objectUrl ?? existingImageUrl ?? null;

    // Is the preview coming from the DB (not a newly picked file)?
    const isExistingPreview = !objectUrl && !!existingImageUrl;

    // ── File handling ─────────────────────────────────────────────────────────

    function handleFile(file: File | null) {
        setError(null);
        if (!file) { clearNewFile(); return; }

        if (file.size > maxSize) {
            setError(`File too large — max allowed is ${formatBytes(maxSize)}.`);
            return;
        }

        if (objectUrl) URL.revokeObjectURL(objectUrl);
        setObjectUrl(URL.createObjectURL(file));
        onChange(file);
    }

    function clearNewFile() {
        if (objectUrl) URL.revokeObjectURL(objectUrl);
        setObjectUrl(null);
        onChange(null);
        if (inputRef.current) inputRef.current.value = '';
        if (replaceRef.current) replaceRef.current.value = '';
    }

    function handleRemove() {
        clearNewFile();
        setError(null);

        // If the preview was the existing DB image, notify the parent
        if (isExistingPreview) {
            onRemoveExisting?.();
        }
    }

    // ── Drag & drop ───────────────────────────────────────────────────────────

    function onDragOver(e: React.DragEvent) {
        e.preventDefault();
        if (!disabled) setIsDragging(true);
    }

    function onDragLeave(e: React.DragEvent) {
        if (!e.currentTarget.contains(e.relatedTarget as Node)) setIsDragging(false);
    }

    function onDrop(e: React.DragEvent) {
        e.preventDefault();
        setIsDragging(false);
        if (disabled) return;
        handleFile(e.dataTransfer.files?.[0] ?? null);
    }

    // ─────────────────────────────────────────────────────────────────────────

    return (
        <div className={cn('space-y-1.5', className)}>
            {label && <Label className="text-sm font-medium">{label}</Label>}

            {/* ── Error ── */}
            {error ? (
                <div className="flex flex-col items-center gap-3 rounded-xl border-2 border-dashed border-destructive/50 bg-destructive/5 px-6 py-8 text-center">
                    <span className="flex h-12 w-12 items-center justify-center rounded-full bg-destructive/10 text-destructive">
                        <AlertIcon className="h-6 w-6" />
                    </span>
                    <div>
                        <p className="text-sm font-medium text-destructive">Upload failed</p>
                        <p className="mt-0.5 text-xs text-destructive/70">{error}</p>
                    </div>
                    <button type="button" onClick={() => setError(null)}
                        className="rounded-lg border border-destructive/30 bg-background px-4 py-1.5 text-xs font-medium text-destructive transition hover:bg-destructive/10 active:scale-95">
                        Try again
                    </button>
                </div>

            ) : preview ? (
                // ── Preview (new file OR existing DB image) ──
                <div className="rounded-xl border border-border bg-muted/20 p-4">

                    {/* "Existing image" badge — only shown in edit mode */}
                    {isExistingPreview && (
                        <div className="mb-3 flex items-center gap-1.5">
                            <span className="inline-flex items-center rounded-full border border-border bg-muted px-2.5 py-0.5 text-[11px] font-medium text-muted-foreground">
                                Current image
                            </span>
                        </div>
                    )}

                    <div className="flex items-center gap-4">
                        {/* Thumbnail */}
                        <div className="relative h-18 w-18 shrink-0 overflow-hidden rounded-lg border border-border shadow-sm">
                            <img src={preview} alt="Preview" className="h-full w-full object-cover" />
                        </div>

                        {/* Meta */}
                        <div className="min-w-0 flex-1">
                            <p className="truncate text-sm font-medium leading-tight text-foreground">
                                {value?.name ?? 'Saved image'}
                            </p>
                            {value && (
                                <p className="mt-0.5 text-xs text-muted-foreground">
                                    {formatBytes(value.size)} · {getFileType(value)}
                                </p>
                            )}
                            <div className="mt-2.5 h-1 overflow-hidden rounded-full bg-muted">
                                <div className="h-full w-full rounded-full bg-green-800" />
                            </div>
                        </div>
                    </div>

                    {!disabled && (
                        <div className="mt-3 flex gap-2">
                            <label className="flex flex-1 cursor-pointer items-center justify-center gap-1.5 rounded-lg border border-border bg-background py-2 text-xs font-medium text-foreground transition hover:bg-muted/50 active:scale-[0.98]">
                                <RefreshIcon className="h-3.5 w-3.5" />
                                Replace
                                <input ref={replaceRef} type="file" accept={accept} className="hidden"
                                    onChange={(e) => handleFile(e.target.files?.[0] ?? null)} />
                            </label>

                            <button type="button" onClick={handleRemove}
                                className="flex flex-1 items-center justify-center gap-1.5 rounded-lg border border-destructive/30 bg-destructive/5 py-2 text-xs font-medium text-destructive transition hover:bg-destructive/10 active:scale-[0.98] cursor-pointer">
                                <TrashIcon className="h-3.5 w-3.5" />
                                Remove
                            </button>
                        </div>
                    )}
                </div>

            ) : (
                // ── Empty / drag ──
                <div onDragOver={onDragOver} onDragLeave={onDragLeave} onDrop={onDrop}
                    className={cn(
                        'flex flex-col items-center gap-3 rounded-xl border-2 border-dashed px-6 py-8 text-center transition-colors duration-200',
                        disabled
                            ? 'cursor-not-allowed border-border/50 bg-muted/20 opacity-50'
                            : isDragging
                                ? 'border-primary bg-primary/5'
                                : 'border-border bg-muted/20 hover:border-primary/50 hover:bg-muted/40',
                    )}>
                    <span className={cn(
                        'flex h-11 w-11 items-center justify-center rounded-full border transition-colors duration-200',
                        isDragging
                            ? 'border-primary/30 bg-primary/10 text-primary'
                            : 'border-border bg-background text-muted-foreground',
                    )}>
                        <UploadIcon className="h-5 w-5" />
                    </span>

                    <div>
                        <p className={cn('text-sm font-medium transition-colors',
                            isDragging ? 'text-primary' : 'text-foreground')}>
                            {isDragging ? 'Drop to upload' : 'Click to upload or drag & drop'}
                        </p>
                        <p className="mt-0.5 text-xs text-muted-foreground">
                            PNG, JPG, WEBP — up to {formatBytes(maxSize)}
                        </p>
                    </div>

                    {!disabled && (
                        <label className="mt-1 inline-flex cursor-pointer items-center gap-1.5 rounded-lg bg-primary px-5 py-2 text-xs font-medium text-primary-foreground transition hover:bg-primary/90 active:scale-95">
                            Browse files
                            <input ref={inputRef} type="file" accept={accept} className="hidden"
                                onChange={(e) => handleFile(e.target.files?.[0] ?? null)} />
                        </label>
                    )}
                </div>
            )}
        </div>
    );
}