import { useEffect, useRef, useState } from 'react';
import { Label } from '@heroui/react';
import { ArrowDownTrayIcon, ArrowsPointingOutIcon, CloudArrowUpIcon, DocumentIcon, XMarkIcon } from '@heroicons/react/24/solid';
import { useUploadStore } from '@/store/useUploadStore';

interface FileFieldProps {
    label: string;
    value?: string[] | string | null;
    onChange: (urls: string[]) => void;
    folder?: string;
    max?: number;
    uploadUrl?: string;
    accept?: string;
    hint?: string;
    fileDetails?: Record<string, { file_size?: number; uploader?: string; uploaded_at?: string }>;
}

const isImage = (url: string) => /\.(png|jpe?g|gif|webp|svg)(\?.*)?$/i.test(url);
const isPdf = (url: string) => /\.pdf(\?.*)?$/i.test(url);
const getThumbUrl = (url: string) => {
    if (!url || !isImage(url)) return url;
    const parts = url.split('/');
    const last = parts.pop() ?? '';
    if (last.startsWith('thumb_')) return url;
    return [...parts, `thumb_${last}`].join('/');
};
const fileName = (url: string) => {
    try {
        return decodeURIComponent(url.split('?')[0].split('/').pop() ?? '');
    } catch {
        return url.split('/').pop() ?? '';
    }
};

const formatBytes = (bytes?: number) => {
    if (!bytes || bytes === 0) return '';
    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
};

export function FileField({
    label,
    value: rawValue,
    onChange,
    folder = 'kegiatan',
    max,
    uploadUrl = '/files',
    accept = 'image/*,application/pdf',
    hint,
    fileDetails = {},
}: FileFieldProps) {
    const value: string[] = Array.isArray(rawValue)
        ? rawValue
        : typeof rawValue === 'string' && rawValue !== ''
        ? [rawValue]
        : [];

    const inputRef = useRef<HTMLInputElement>(null);
    const [isDragOver, setIsDragOver] = useState(false);
    const { startUpload, tasks } = useUploadStore();

    const urlsRef = useRef<string[]>(value);

    // Keep urlsRef in sync with value prop
    useEffect(() => {
        urlsRef.current = value;
    }, [value]);

    const activeTasks = tasks.filter(
        (t) => t.folder === folder && t.uploadUrl === uploadUrl && (t.status === 'uploading' || t.status === 'queued'),
    );
    const isUploading = activeTasks.length > 0;
    const atMax = max !== undefined && (value.length + activeTasks.length) >= max;

    function handleFiles(files: File[]) {
        if (files.length === 0) return;
        const selected = max !== undefined ? files.slice(0, max - urlsRef.current.length) : files;

        selected.forEach((file) => {
            startUpload(file, folder, uploadUrl, (newUrl) => {
                if (!urlsRef.current.includes(newUrl)) {
                    const next = [...urlsRef.current, newUrl];
                    urlsRef.current = next;
                    onChange(next);
                }
            });
        });
    }

    function removeAt(index: number) {
        const next = urlsRef.current.filter((_, i) => i !== index);
        urlsRef.current = next;
        onChange(next);
    }

    return (
        <div className="flex flex-col gap-1.5">
            <Label>{label}</Label>

            {value.length > 0 && (
                <div className={max === 1 ? '' : 'grid grid-cols-2 sm:grid-cols-4 md:grid-cols-6 gap-2.5 sm:gap-3'}>
                    {value.map((url, i) => (
                        <div key={url + i} className="flex flex-col gap-1">
                            <div
                                className={`group relative rounded-xl border border-gray-200 bg-gray-50 overflow-hidden ${
                                    max === 1 ? 'aspect-video w-full' : 'aspect-square'
                                }`}
                            >
                                {isImage(url) ? (
                                    <img
                                        src={getThumbUrl(url)}
                                        onError={(e) => {
                                            const target = e.currentTarget;
                                            if (target.src !== url) {
                                                target.src = url;
                                            }
                                        }}
                                        alt={label}
                                        loading="lazy"
                                        decoding="async"
                                        className="w-full h-full object-cover"
                                    />
                                ) : isPdf(url) ? (
                                    <div className="flex flex-col w-full h-full items-center justify-center bg-gray-100 text-gray-500 gap-1 p-2">
                                        <DocumentIcon className="w-8 h-8 text-red-500" />
                                        <span className="text-[10px] font-semibold uppercase tracking-wider">PDF</span>
                                    </div>
                                ) : (
                                    <div className="flex flex-col w-full h-full items-center justify-center bg-gray-100 text-gray-500 gap-1 p-2">
                                        <DocumentIcon className="w-8 h-8 text-sky-500" />
                                        <span className="text-[10px] font-semibold uppercase tracking-wider">Media</span>
                                    </div>
                                )}

                                <div className="absolute inset-0 flex items-center justify-center gap-2 bg-black/0 opacity-0 transition-all group-hover:bg-black/40 group-hover:opacity-100">
                                    <a
                                        href={url}
                                        target="_blank"
                                        rel="noreferrer"
                                        className="rounded-full bg-white/20 p-2 text-white hover:bg-white/40"
                                        aria-label="Lihat ukuran penuh"
                                        title="Lihat"
                                    >
                                        <ArrowsPointingOutIcon className="w-5 h-5" />
                                    </a>
                                    <a
                                        href={url}
                                        download
                                        target="_blank"
                                        rel="noreferrer"
                                        className="rounded-full bg-sky-600 p-2 text-white hover:bg-sky-700"
                                        aria-label="Unduh berkas"
                                        title="Unduh"
                                    >
                                        <ArrowDownTrayIcon className="w-5 h-5" />
                                    </a>
                                </div>

                                <button
                                    type="button"
                                    onClick={() => removeAt(i)}
                                    className="absolute top-1 right-1 rounded-full bg-black/60 p-1 text-white hover:bg-red-600 z-10"
                                    aria-label="Hapus file"
                                >
                                    <XMarkIcon className="w-3.5 h-3.5" />
                                </button>
                            </div>
                            <div className="flex flex-col gap-0.5">
                                <div className="flex items-center justify-between gap-1">
                                    <span className="text-xs leading-tight text-gray-700 font-medium truncate flex-1" title={fileName(url)}>
                                        {fileName(url)}
                                    </span>
                                    <a
                                        href={url}
                                        download
                                        target="_blank"
                                        rel="noreferrer"
                                        className="text-sky-600 hover:text-sky-800 p-0.5 shrink-0"
                                        title="Unduh"
                                    >
                                        <ArrowDownTrayIcon className="w-3.5 h-3.5" />
                                    </a>
                                </div>
                                <div className="flex items-center justify-between text-[10px] text-gray-400">
                                    <span>{formatBytes(fileDetails[url]?.file_size)}</span>
                                    {fileDetails[url]?.uploader && (
                                        <span className="truncate max-w-[120px]" title={`Pengunggah: ${fileDetails[url]?.uploader}`}>
                                            Oleh: <strong className="text-gray-600">{fileDetails[url]?.uploader}</strong>
                                        </span>
                                    )}
                                </div>
                                {fileDetails[url]?.uploaded_at && (
                                    <div className="text-[9px] text-gray-400">
                                        {fileDetails[url]?.uploaded_at}
                                    </div>
                                )}
                            </div>
                        </div>
                    ))}
                </div>
            )}

            {!atMax && (
                <>
                    <div
                        role="button"
                        aria-busy={isUploading}
                        tabIndex={0}
                        onClick={() => inputRef.current?.click()}
                        onKeyDown={(e) => e.key === 'Enter' && inputRef.current?.click()}
                        onDragOver={(e) => {
                            e.preventDefault();
                            setIsDragOver(true);
                        }}
                        onDragLeave={() => setIsDragOver(false)}
                        onDrop={(e) => {
                            e.preventDefault();
                            setIsDragOver(false);
                            const files = Array.from(e.dataTransfer.files);
                            handleFiles(files);
                        }}
                        onPaste={(e) => {
                            const files = Array.from(e.clipboardData.items)
                                .map((item) => (item.kind === 'file' ? item.getAsFile() : null))
                                .filter((f): f is File => !!f);
                            handleFiles(files);
                        }}
                        className={`flex flex-col items-center justify-center gap-1.5 rounded-xl border-2 border-dashed px-4 py-6 text-center transition-colors cursor-pointer ${
                            isDragOver
                                ? 'border-sky-500 bg-sky-50'
                                : 'border-gray-300 bg-white hover:border-sky-300 hover:bg-gray-50'
                        }`}
                    >
                        <CloudArrowUpIcon className="w-6 h-6 text-gray-400" />
                        <p className="text-sm text-gray-600">
                            <span className="font-medium text-sky-600">Klik untuk unggah</span> atau seret file ke sini
                        </p>
                        <p className="text-xs text-gray-400">
                            {hint ?? (max === 1 ? 'Gambar atau PDF' : 'Gambar atau PDF, bisa lebih dari satu')} - bisa juga tempel (paste) dari clipboard
                        </p>
                    </div>

                    <input
                        ref={inputRef}
                        type="file"
                        accept={accept}
                        multiple={max !== 1}
                        className="hidden"
                        onChange={(e) => {
                            const files = Array.from(e.target.files ?? []);
                            handleFiles(files);
                            e.target.value = '';
                        }}
                    />
                </>
            )}
        </div>
    );
}
