import React, { useRef, useEffect, useState } from 'react';
import './customfileupload.scss';
import { toastWarn } from "../../../../services/toaster";
import EmptyList from "../../DuaList/EmptyList";

type CustomFileUploadProps = CustomFileUploadPropsMultiple | CustomFileUploadPropsSingle

type CustomFileUploadPropsMultiple = {
    multiple: true
    file: File[],
    onChange: (f: any) => void
    id?: string
    maxSize?: number
    accept?: string
    disabled?: boolean
}

type CustomFileUploadPropsSingle = {
    multiple?: false
    file: File | string | null,
    onChange: (f: any) => void
    id?: string
    maxSize?: number
    accept?: string
    disabled?: boolean
}

/** Extracts the uppercased extension from a filename, e.g. "report.pdf" → "PDF" */
const getExtension = (name: string): string =>
    name.includes('.') ? name.split('.').pop()!.toUpperCase() : '—';

/** Color map for file type icons */
const FILE_TYPE_COLORS: Record<string, string> = {
    PDF:  '#e63946',
    DOC:  '#2563eb',
    DOCX: '#2563eb',
    XLS:  '#16a34a',
    XLSX: '#16a34a',
    PPT:  '#ea580c',
    PPTX: '#ea580c',
    ZIP:  '#7c3aed',
    RAR:  '#7c3aed',
    JPG:  '#060159',
    JPEG: '#060159',
    PNG:  '#060159',
    GIF:  '#060159',
    IMG:  '#060159',
};

const getIconLabel = (ext: string): string => {
    const map: Record<string, string> = { DOCX: 'DOC', XLSX: 'XLS', PPTX: 'PPT', JPEG: 'JPG', RAR: 'ZIP' };
    return map[ext] ?? ext;
};

/**
 * Colored document icon — matches the icon set in the design.
 * If you prefer to use your own image files, swap this with:
 *   <img src={`/icons/${ext.toLowerCase()}.svg`} width={44} height={52} alt={ext} />
 */
const FileIcon = ({ ext }: { ext: string }) => {
    const bg = FILE_TYPE_COLORS[ext] ?? '#64748b';
    const label = getIconLabel(ext).slice(0, 4); // guard against long exts

    return (
        <svg
            width="44"
            height="52"
            viewBox="0 0 44 52"
            xmlns="http://www.w3.org/2000/svg"
            aria-hidden="true"
            style={{ flexShrink: 0 }}
        >
            {/* Page body */}
            <rect width="44" height="52" rx="5" fill={bg} />
            {/* Folded corner shadow */}
            <path d="M28 2 L42 16 L28 16 Z" fill="rgba(0,0,0,0.20)" />
            {/* Folded corner highlight */}
            <path d="M28 2 L28 16 L42 16" fill="rgba(255,255,255,0.18)" />
            <path d="M28 2 L28 16 L42 16" fill="none" stroke="rgba(255,255,255,0.35)" strokeWidth="1" />
            {/* Extension label */}
            <text
                x="22"
                y="41"
                textAnchor="middle"
                fill="white"
                fontSize={label.length > 3 ? '9' : '11'}
                fontWeight="700"
                fontFamily="system-ui, sans-serif"
                letterSpacing="0.5"
            >
                {label}
            </text>
        </svg>
    );
};

/** Trash icon SVG */
const TrashIcon = () => (
    <svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24"
         fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
        <polyline points="3 6 5 6 21 6" />
        <path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" />
        <path d="M10 11v6M14 11v6" />
        <path d="M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2" />
    </svg>
);

const CustomFileUpload = ({ file, accept, onChange, multiple, id = 'file', disabled, maxSize }: CustomFileUploadProps) => {
    const inputRef = useRef<HTMLInputElement>(null);
    const scrollGuardRef = useRef<HTMLDivElement>(null);
    const [isOverflowing, setIsOverflowing] = useState(false);
    const [activeIndex, setActiveIndex] = useState<number | null>(null);
    const [isDragging, setIsDragging] = useState(false);

    const hasFile = (multiple === true && file.length > 0) || (multiple !== true && Boolean(file));

    let placeholder = multiple
        ? 'ΣΥΡΕΤΕ ΑΡΧΕΙΟ/ΑΡΧΕΙΑ ΕΔΩ Η ΠΑΤΗΣΤΕ ΓΙΑ ΜΕΤΑΦΟΡΤΩΣΗ'
        : 'ΣΥΡΕΤΕ ΑΡΧΕΙΟ ΕΔΩ Η ΠΑΤΗΣΤΕ ΓΙΑ ΜΕΤΑΦΟΡΤΩΣΗ';

    if (maxSize) {
        placeholder += ` (Μέγιστο μέγεθος αρχείου: ${maxSize / 1048576}MB)`;
    }

    /** Shared validation + state-merge logic used by both the file picker and drag-and-drop. */
    const validateAndAdd = (incoming: FileList) => {
        if (disabled || !incoming || incoming.length === 0) return;

        if (maxSize) {
            for (let i = 0; i < incoming.length; i++) {
                if (incoming[i].size > maxSize) {
                    toastWarn(`Max size per file allowed: ${maxSize / 1048576}MB`);
                    return;
                }
            }
        }

        if (!multiple) {
            onChange(incoming[0]);
        } else {
            const filesArr = Array.from(incoming);
            const existing = file as File[];
            const merged = [...existing];
            for (const f of filesArr) {
                if (!merged.some(ex => ex.name === f.name && ex.size === f.size)) {
                    merged.push(f);
                }
            }
            onChange(merged);
        }
    };

    const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        if (disabled) return;
        const files = e.target.files;
        if (files) validateAndAdd(files);
        if (inputRef.current) inputRef.current.value = '';
    };

    const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
        e.preventDefault();
        e.stopPropagation();
        if (!disabled) setIsDragging(true);
    };

    const handleDragLeave = (e: React.DragEvent<HTMLDivElement>) => {
        e.preventDefault();
        e.stopPropagation();
        setIsDragging(false);
    };

    const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {
        e.preventDefault();
        e.stopPropagation();
        setIsDragging(false);
        if (disabled) return;
        validateAndAdd(e.dataTransfer.files);
    };

    const removeFile = (e: React.MouseEvent, index: number) => {
        e.preventDefault();
        e.stopPropagation();
        if (disabled) return;

        if (!multiple) {
            onChange(null);
        } else {
            onChange((file as File[]).filter((_, i) => i !== index));
        }

        setActiveIndex(null);
    };

    const fileList: { name: string; index: number }[] = (() => {
        if (multiple) {
            return (file as File[]).map((f, i) => ({ name: f.name, index: i }));
        }
        if (!file) return [];
        const name = typeof file === 'string'
            ? file.split('/').pop() ?? file
            : (file as File).name;
        return [{ name, index: 0 }];
    })();

    useEffect(() => {
        const el = scrollGuardRef.current;
        if (!el) return;
        const check = () => setIsOverflowing(el.scrollHeight > el.clientHeight);
        check();
        const ro = new ResizeObserver(check);
        ro.observe(el);
        return () => ro.disconnect();
    }, [file]);

    // Reset active selection when file list shrinks
    useEffect(() => {
        if (activeIndex !== null && activeIndex >= fileList.length) {
            setActiveIndex(null);
        }
    }, [fileList.length, activeIndex]);

    return (
        <>
            <div
                className={`custom-file-upload${disabled ? ' disabled' : ''}${isDragging ? ' is-dragging' : ''}`}
                onDragEnter={handleDragOver}
                onDragOver={handleDragOver}
                onDragLeave={handleDragLeave}
                onDrop={handleDrop}
            >
                <input
                    ref={inputRef}
                    accept={accept}
                    type="file"
                    id={id}
                    disabled={disabled}
                    onChange={handleChange}
                    multiple={multiple}
                />
                <label htmlFor={disabled ? undefined : id} className="drop-zone">
                    <div style={{ color: '--generic-block-border-hover' }} className="name">
                        {placeholder} <br />
                        <span style={{ color: '#111111' }}>(Μέγιστο μέγεθος αρχείου: 10MB)</span>
                    </div>
                </label>
            </div>

            {!hasFile ? (
                <div className="emptylist">
                    <EmptyList>
                        Δεν έχετε προσθέσει αρχεία ακόμη
                    </EmptyList>
                </div>
            ) : (
                <div
                    ref={scrollGuardRef}
                    className={`file-list-scroll-guard mt-4${isOverflowing ? ' is-overflowing' : ''}`}
                >
                    <ul className="file-list">
                        {fileList.map(({ name, index }) => {
                            const ext = getExtension(name);
                            const isActive = activeIndex === index;
                            return (
                                <li
                                    key={`${name}-${index}`}
                                    className={`file-list__item${isActive ? ' file-list__item--active' : ''}`}
                                    onClick={() => setActiveIndex(isActive ? null : index)}
                                >
                                    <FileIcon ext={ext} />
                                    <span className="file-list__name" title={name}>{name}</span>
                                    <button
                                        type="button"
                                        className="file-list__remove"
                                        onClick={(e) => removeFile(e, index)}
                                        disabled={disabled}
                                        aria-label={`Remove ${name}`}
                                    >
                                        <TrashIcon />
                                    </button>
                                </li>
                            );
                        })}
                    </ul>
                </div>
            )}
        </>
    );
};

export default CustomFileUpload;