
import React, { ReactNode, useEffect, useState } from "react";
import {
    Dialog,
    DialogContent,
    DialogFooter,
    DialogHeader,
    DialogTitle,
    DialogTrigger,
} from "@/components/ui/dialog";
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
import { Button } from "@/components/ui/button";
import { CloudUpload, ImagePlus, Loader, LucideIcon, Trash2, UploadCloud } from "lucide-react";
import { Spinner } from "../ui/spinner";
import axios from "axios";
import { toast } from "sonner";
import { Checkbox } from "../ui/checkbox";
import { Label } from "../ui/label";
import { Input } from "../ui/input";
import { cn } from "@/lib/utils";
import * as LucideIcons from "lucide-react"
import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip";
import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger } from "../ui/context-menu";
import { ActiveTabType, UploadFolderType } from "@/types/dashboard/image";

type SelectImageProp = {
    id: number,
    url: string,
    file_size: string
}


type Props = {
    selected: SelectImageProp[],
    onSelect: (images: SelectImageProp[]) => void;
    max: number,
    icon?: string,
    onSelectIcon?: (icon: string) => void
    className?: string,
    children?: ReactNode,
    defaultTab?: ActiveTabType
    disabled?: boolean,
    iconTab?: boolean,
    uploadFolderType?: UploadFolderType,
    itemName?: string;   // for filename + alt
    itemId?: number;     // optional (for folder structure)
};

type ImageItem = {
    id: number;
    url: string;
    title: string;
    file_size: number;
    width: number;
    height: number;
};

function formatFileSize(bytes: number) {
    if (bytes < 1024) return bytes + ' B';
    if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(2) + ' KB';
    return (bytes / 1024 / 1024).toFixed(2) + ' MB';
}


export default function ImagePicker({
    selected,
    onSelect,
    max,
    className,
    children,
    icon,
    onSelectIcon,
    defaultTab,
    disabled,
    iconTab,
    uploadFolderType,
    itemName,
    itemId
}: Props) {

    const [open, setOpen] = useState(false);
    const [activeTab, setActiveTab] = useState<string>(defaultTab || "upload");


    // Icons
    const [search, setSearch] = useState<string>('')
    const [selectedIcon, setSelectedIcon] = useState(icon || '')

    const [files, setFiles] = useState<File[]>([]);
    const [uploadProgress, setUploadProgress] = useState<Record<string, number>>({});
    const [isDragging, setIsDragging] = useState(false);

    const [uploadedImageLoading, setUploadedImaggeLoading] = useState(false)
    const [uploadedImages, setUploadedImages] = useState<ImageItem[]>([]);
    const [selectedImages, setSelectedImages] = useState<SelectImageProp[]>([]);

    const disabledImageUplaod = (selected.length + selectedImages.length + files.length) >= max

    const isUploading = Object.values(uploadProgress).some(p => p > 0);
    const totalProgress = files.length > 0 ? Math.round(Object.values(uploadProgress).reduce((a, b) => a + b, 0) / files.length) : 0;


    // Icons
    // const Icon = LucideIcons[icon as keyof typeof LucideIcons] as LucideIcon
    const SelectedIcon = LucideIcons[selectedIcon as keyof typeof LucideIcons] as LucideIcon

    const iconNames = Object.keys(LucideIcons).filter(name =>
        name.toLowerCase().includes(search.toLowerCase())
    )

    const isDuplicate = (file: File, existing: File[]) => {
        return existing.some(
            (f) =>
                f.name === file.name &&
                f.size === file.size &&
                f.lastModified === file.lastModified
        );
    };

    const validateFiles = (files: File[]) => {
        const valid: File[] = [];
        const invalid: File[] = [];

        files.forEach((f) => {
            const isValidType = ['image/png', 'image/jpeg', 'image/webp'].includes(f.type);
            const isValidSize = f.size <= 2_000_000;

            if (isValidType && isValidSize) {
                valid.push(f);
            } else {
                invalid.push(f);
            }
        });

        return { valid, invalid };
    };

    const handleSelectIcon = (name: string) => {

        onSelect([])
        if (onSelectIcon) {
            onSelectIcon(name)
        }

    }

    // Handle Image selection from local
    const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        if (!e.target.files) return;

        const newFiles = Array.from(e.target.files);

        const { valid, invalid } = validateFiles(newFiles);

        const uniqueValid = valid.filter((file) => {
            if (isDuplicate(file, files)) {
                toast.warning(`${file.name} is already added`);
                return false;
            }
            return true;
        });

        const remainingSlots = max - selected.length - selectedImages.length - files.length;

        if (remainingSlots <= 0) {
            toast.error(`You can only select up to ${max} images.`);
            return;
        }

        const allowedFiles = uniqueValid.slice(0, remainingSlots);

        setFiles((prev) => [...prev, ...allowedFiles]);

        // invalid feedback
        invalid.forEach((file) => {
            if (file.size > 2_000_000) {
                toast.error(`${file.name} is larger than 2MB`);
            } else {
                toast.error(`${file.name} format not supported`);
            }
        });

        e.target.value = "";
    };

    // Upload Images
    const handleConfirm = async () => {
        if (files.length === 0) return;

        const uploadedImage = []

        for (const file of files) {
            const formData = new FormData();
            formData.append('image', file);
            formData.append('folderType', uploadFolderType || 'general');
            formData.append('item_name', itemName || '');
            formData.append('item_id', itemId ? String(itemId) : '');

            try {
                const { data } = await axios.post('/dashboard/images', formData, {
                    headers: { 'Content-Type': 'multipart/form-data' },
                    onUploadProgress: (progressEvent) => {
                        const percentCompleted = Math.round(
                            (progressEvent.loaded * 100) / (progressEvent.total || 1)
                        );
                        setUploadProgress(prev => ({ ...prev, [file.name]: percentCompleted }));
                    },
                    withCredentials: true,
                });

                if (data.success) {
                    const image = {
                        id: data.image.id,
                        url: data.image.url,
                        file_size: formatFileSize(data.image.file_size)
                    }
                    uploadedImage.push(image)

                    setSelectedImages(prev => [...prev, image]);
                }
            } catch (err) {
                console.error('Upload failed:', err);
                toast.error(`${file.name} upload failed!`);
            }
        }

        // send all uploaded URLs to parent
        if (onSelectIcon) {
            onSelectIcon('')
        }
        onSelect(uploadedImage)
        handleClose()
    };

    // Load uploaded images
    const loadUploadedImages = () => {
        setUploadedImaggeLoading(true)
        axios.get("/dashboard/images") // Laravel API endpoint
            .then(res => {
                console.log(res);
                const images = res.data.images.filter((img: ImageItem) => !selected.some(i => i.id === img.id))
                setUploadedImages(images);
                setUploadedImaggeLoading(false)
            })
            .catch(err => {
                setUploadedImaggeLoading(false)
                console.error("Failed to fetch gallery images", err);
                toast.error('Failed to fetch uploaded images');
            });

        setSelectedIcon(icon || '')
    }

    const toggleSelect = (image: SelectImageProp) => {
        setSelectedImages((prev) => prev.some(i => i.id === image.id) ? prev.filter((u) => u.id !== image.id) : [...prev, image]);
    };

    // reset state asn close
    const handleClose = () => {
        setOpen(false)
        setFiles([]);
        setUploadProgress({});
        setUploadedImages([])
        setSelectedImages([])
        setSearch('')
        setSelectedIcon('')
    }

    const clear = () => {
        onSelect([])

        if (onSelectIcon) {
            onSelectIcon('')
        }
    }

    useEffect(() => {
        if (!open) return;
        loadUploadedImages()
    }, [open]);


    return (
        <Dialog open={open} onOpenChange={setOpen}>

            <ContextMenu>
                <ContextMenuTrigger asChild disabled={disabled} >
                    <DialogTrigger disabled={disabled} asChild>
                        {children ?
                            <button className={cn(!disabled && 'hover:scale-101 active:scale-98 transform duration-100 ease-in', className)}>
                                {children}
                            </button>
                            :
                            <Button variant="outline" className='w-fit'>  <ImagePlus className="w-4 h-4 mr-2" />   Upload & Select Images  </Button>}
                    </DialogTrigger>
                </ContextMenuTrigger>
                <ContextMenuContent>
                    <ContextMenuItem onClick={clear}>Clear</ContextMenuItem>
                </ContextMenuContent>
            </ContextMenu>


            <DialogContent className="w-full min-h-[80vh] flex flex-col justify-between sm:max-w-240">
                <DialogHeader>
                    <DialogTitle className="flex gap-2 items-center"><UploadCloud className="w-6 h-6 text-primary" /> Upload & Select Images</DialogTitle>
                </DialogHeader>

                <Tabs value={activeTab} onValueChange={setActiveTab} className="flex-1 ">
                    <TabsList >
                        <TabsTrigger value="upload">Upload</TabsTrigger>
                        <TabsTrigger value="gallery">Gallery</TabsTrigger>
                        {iconTab && <TabsTrigger value="icons">Icons</TabsTrigger>}
                    </TabsList>

                    {/* Upload Tab */}
                    <TabsContent value="upload" className=" flex gap-4 mt-2">

                        <Label
                            className={`border-2 border-dashed dark:border-neutral-600 min-h-[60vh]  max-h-[60vh]  rounded-lg p-6 text-center ${files.length === 0 ? 'w-full' : 'w-1/2'} mx-auto flex flex-col items-center justify-center gap-2 ${disabledImageUplaod ? 'cursor-no-drop' : 'cursor-pointer hover:scale-101 hover:border-blue-300 hover:bg-muted'} transition-all duration-200 ${(isDragging && !disabledImageUplaod) ? 'border-blue-500 bg-blue-50 scale-101' : 'border-gray-300 '}`}
                            onDragOver={(e) => {
                                e.preventDefault();
                                // if (disabledImageUplaod) return
                                setIsDragging(true);
                            }}
                            onDragLeave={(e) => {
                                e.preventDefault();
                                setIsDragging(false);
                            }}
                            onDrop={(e) => {
                                e.preventDefault();
                                if (disabledImageUplaod) return
                                setIsDragging(false);
                                const droppedFiles = Array.from(e.dataTransfer.files);

                                const { valid, invalid } = validateFiles(droppedFiles);

                                const uniqueValid = valid.filter((file) => {
                                    if (isDuplicate(file, files)) {
                                        toast.warning(`${file.name} is already added`);
                                        return false;
                                    }
                                    return true;
                                });

                                setFiles((prev) => [...prev, ...uniqueValid]);

                                invalid.forEach((file) => {
                                    if (file.size > 2_000_000) {
                                        toast.error(`${file.name} is larger than 2MB`);
                                    } else {
                                        toast.error(`${file.name} format not supported`);
                                    }
                                });
                            }}

                        >
                            <CloudUpload className="w-14 h-14 text-gray-400" />
                            <p className="text-sm text-gray-500">   Click or drag & drop images here or choose from <br /> your device  </p>
                            <p className="text-xs text-gray-400">JPG, PNG, WebP | Max size: 2MB each</p>
                            <Input
                                type="file"
                                accept="image/png, image/jpeg, image/webp"
                                multiple
                                className="hidden"
                                disabled={isUploading || disabledImageUplaod}
                                onChange={handleFileChange}
                            />
                        </Label>

                        {
                            files.length ? <div className="space-y-2 no-scrollbar min-h-[60vh]  max-h-[60vh] overflow-y-auto w-1/2 ">
                                {files.map((file, index) => (
                                    <div key={index} className="flex items-center gap-2 border p-1.5 pr-2 rounded-sm bg-neutral-50 dark:bg-neutral-900">
                                        <img
                                            src={URL.createObjectURL(file)}
                                            alt={file.name}
                                            className="w-16 h-12 border object-cover rounded-sm"
                                        />
                                        <div className="flex-1 text-sm">
                                            <p className="truncate max-w-75">{file.name}</p>
                                            <p>{formatFileSize(file.size)}</p>
                                            {uploadProgress[file.name] && (
                                                <div className="w-full bg-gray-200 h-1.5 rounded mt-1">
                                                    <div className="bg-blue-500 h-1.5 rounded" style={{ width: `${uploadProgress[file.name]}%` }} />
                                                </div>
                                            )}
                                        </div>
                                        <Button variant='ghost' size='icon-sm' className="rounded-full text-red-400" onClick={() => setFiles(prev => prev.filter(f => f.name !== file.name))}>
                                            <Trash2 className="w-4 h-4" />
                                        </Button>
                                    </div>
                                ))}
                            </div> : null
                        }
                    </TabsContent>

                    {/* Select Tab */}
                    <TabsContent value="gallery" className="mt-2  ">
                        <div className="grid  h-full   grid-cols-5 gap-3 p-1 min-h-[60vh] max-h-[60vh] overflow-y-auto">
                            {
                                uploadedImageLoading ? <div className="col-span-5 row-span-1 text-center flex justify-center items-center flex-col text-gray-500 py-6 border rounded-lg">
                                    <Loader className="w-12 h-12   text-sm animate-spin  mx-auto mb-2 text-gray-400" />
                                    <p>Image are loading..</p>
                                </div>
                                    : <>
                                        {uploadedImages.length > 0 ? (
                                            uploadedImages.map((img, index) => {

                                                const image = { id: img.id, url: img.url, file_size: formatFileSize(img.file_size) }

                                                const isSelected = selectedImages.some(i => i.id === img.id);
                                                const hide = !isSelected && (selected.length + selectedImages.length) >= max

                                                return (
                                                    <div key={index} onClick={() => !hide && toggleSelect(image)} className={`cursor-pointer max-h-fit  border relative rounded-sm group overflow-hidden ${!hide && 'hover:ring-2 hover:ring-primary'}   flex flex-col items-center   transform ease-in duration-200 ${isSelected ? 'ring-2 ring-blue-500 scale-96' : ''}  `} >
                                                        {
                                                            !hide && <Checkbox
                                                                checked={isSelected}
                                                                onChange={() => toggleSelect(image)}

                                                                className="absolute rounded-sm top-1.5 left-1.5 z-10 cursor-pointer"
                                                            />
                                                        }

                                                        <img src={img.url} alt={img.title} className="w-full h-24 max-h-24 object-contain rounded-sm" />

                                                        <div className="w-full absolute bottom-0 right-0 left-0 opacity-0 group-hover:opacity-100 bg-linear-to-t from-black/60 to-black/40 text-xs text-center py-1 text-white transition-all duration-200">
                                                            <p className="truncate font-medium">{img.title}</p>
                                                            <p>{img.width}×{img.height}px | {formatFileSize(img.file_size)}</p>
                                                        </div>
                                                    </div>
                                                );
                                            })
                                        ) : (
                                            <div className="col-span-5  text-sm row-span-1 text-center flex justify-center items-center flex-col text-gray-500 py-6 border rounded-lg">
                                                <ImagePlus className="w-12 h-12 mx-auto mb-2 text-gray-400" />
                                                <p>No images uploaded yet.</p>
                                            </div>
                                        )}
                                    </>
                            }

                        </div>
                    </TabsContent>

                    {iconTab &&
                        <TabsContent value="icons" className="mt-2">
                            <div className="flex-1 flex flex-col gap-4 min-h-[50vh] max-h-[60vh]">
                                {/* Preview + Search */}
                                <div className="flex flex-col md:flex-row gap-4 items-start md:items-center">
                                    {selected && SelectedIcon && (
                                        <div className="flex items-center gap-3 bg-gray-50 border dark:bg-neutral-950  rounded-sm p-2  w-full md:w-auto">
                                            <SelectedIcon className="w-12 h-12 text-blue-600 dark:text-primary" />
                                            <span className="font-mono text-sm text-gray-700 dark:text-neutral-200">{selectedIcon}</span>
                                        </div>
                                    )}

                                    <div className="flex-1 space-y-2">
                                        <Label>Search Icon</Label>
                                        <Input
                                            type="text"
                                            value={search}
                                            onChange={e => setSearch(e.target.value)}
                                            placeholder="Type icon name..."
                                            className="mt-1"
                                        />
                                    </div>
                                </div>

                                {/* Icon Grid */}
                                <div className="grid grid-cols-14 gap-3 flex-1 overflow-auto  bg-background">
                                    {iconNames.length > 0 ? (
                                        iconNames.slice(0, 300).map(name => {
                                            const Icon = LucideIcons[name as keyof typeof LucideIcons] as any
                                            return (
                                                <Tooltip key={name}>
                                                    <TooltipTrigger asChild>
                                                        <div
                                                            className={`flex flex-col gap-1 items-center justify-center cursor-pointer p-2 h-12 w-12 border rounded-sm transition  ${selectedIcon === name ? 'bg-blue-200 dark:bg-primary' : 'hover:bg-blue-100 hover:dark:bg-blue-950'}`}
                                                            onClick={() => setSelectedIcon(name)}
                                                        >
                                                            <Icon className="w-6 h-6 text-gray-700 dark:text-neutral-200" />
                                                        </div>

                                                    </TooltipTrigger>
                                                    <TooltipContent>
                                                        <p>{name}</p>
                                                    </TooltipContent>
                                                </Tooltip>

                                            )
                                        })
                                    ) : (
                                        <div className="col-span-6 text-center text-gray-400 py-4">No icons found</div>
                                    )}
                                </div>
                            </div>
                        </TabsContent>
                    }
                </Tabs>

                <DialogFooter>
                    <Button disabled={isUploading} variant="outline" onClick={handleClose}>Close</Button>
                    {activeTab === 'upload' && <Button disabled={files.length === 0 || isUploading} onClick={handleConfirm}> {isUploading ? <><Spinner /> Uploading {totalProgress}%</> : 'Upload & Use'} </Button>}
                    {activeTab === 'gallery' && <Button disabled={selectedImages.length === 0} onClick={() => { onSelect(selectedImages); handleClose() }} >  Use Selected ({selectedImages.length} / {max - selected.length}) </Button>}
                    {activeTab === 'icons' && <Button disabled={selectedIcon === ''} onClick={() => { handleSelectIcon(selectedIcon); handleClose() }} >  Use Selected Icon </Button>}
                </DialogFooter>
            </DialogContent>
        </Dialog>
    );
}
