import React, { useEffect, useState } from 'react';
import { Dialog } from '@/components/elements/dialog';
import { Button } from '@/components/elements/button';
import { ServerContext } from '@/state/server';
import { useFlashKey } from '../useFlash';
import {
    getTrashContents,
    restoreFromTrash,
    emptyTrash,
    getTrashCleanupSettings,
    TrashCleanupSettings,
} from '../api/server/files/betterFilesApi';
import Spinner from '@/components/elements/Spinner';
import Input from '@/components/elements/Input';
import GreyRowBox from '@/components/elements/GreyRowBox';

const cx = (...parts: Array<string | false | null | undefined>) => parts.filter(Boolean).join(' ');

interface TrashBinModalProps {
    visible: boolean;
    onDismiss: () => void;
    onFilesRestored?: (paths?: string[]) => void;
}

interface TrashFile {
    path: string;
    name: string;
    originalPath: string;
    deletedAt: string;
    size: number;
    isFile: boolean;
}

const TrashBinModal: React.FC<TrashBinModalProps> = ({ visible, onDismiss, onFilesRestored }) => {
    const uuid = ServerContext.useStoreState(state => state.server.data!.uuid);
    const { clearFlashes, clearAndAddHttpError } = useFlashKey('better-files');
    const [loading, setLoading] = useState(false);
    const [trashFiles, setTrashFiles] = useState<TrashFile[]>([]);
    const [selectedFiles, setSelectedFiles] = useState<string[]>([]);
    const [searchQuery, setSearchQuery] = useState('');
    const [showEmptyConfirm, setShowEmptyConfirm] = useState(false);
    const [sortBy, setSortBy] = useState<'date' | 'name' | 'size'>('date');
    const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('desc');
    const [cleanupSettings, setCleanupSettings] = useState<TrashCleanupSettings | null>(null);

    const originalPathByTrashPath = React.useMemo(() => {
        const map = new Map<string, string>();
        for (const file of trashFiles) {
            if (file.path && file.originalPath) {
                map.set(file.path, file.originalPath);
            }
        }
        return map;
    }, [trashFiles]);

    useEffect(() => {
        if (visible) {
            loadTrash();
            loadCleanupSettings();
            setSelectedFiles([]);
            setSearchQuery('');
        }
    }, [visible, uuid]);

    const loadTrash = async () => {
        setLoading(true);
        try {
            const files = await getTrashContents(uuid);
            setTrashFiles(files);
        } catch (error) {
            clearAndAddHttpError(error as Error);
        } finally {
            setLoading(false);
        }
    };

    const loadCleanupSettings = async () => {
        try {
            const settings = await getTrashCleanupSettings(uuid);
            setCleanupSettings(settings);
        } catch (error) {
            setCleanupSettings(null);
        }
    };

    const handleRestore = async () => {
        if (selectedFiles.length === 0) return;

        setLoading(true);
        try {
            await restoreFromTrash(uuid, selectedFiles);
            clearFlashes();
            await loadTrash();
            const restored = selectedFiles
                .map(path => originalPathByTrashPath.get(path))
                .filter((path): path is string => Boolean(path));
            setSelectedFiles([]);
            onFilesRestored?.(restored);
        } catch (error) {
            clearAndAddHttpError(error as Error);
        } finally {
            setLoading(false);
        }
    };

    const handleEmptyTrash = async () => {
        setShowEmptyConfirm(false);
        setLoading(true);
        try {
            const affectedPaths = trashFiles
                .map(file => file.originalPath)
                .filter(Boolean);
            await emptyTrash(uuid);
            clearFlashes();
            await loadTrash();
            setSelectedFiles([]);
            onFilesRestored?.(affectedPaths);
        } catch (error) {
            clearAndAddHttpError(error as Error);
        } finally {
            setLoading(false);
        }
    };

    const toggleFileSelection = (path: string) => {
        setSelectedFiles(prev =>
            prev.includes(path)
                ? prev.filter(p => p !== path)
                : [...prev, path]
        );
    };

    const selectAllVisible = () => {
        const visiblePaths = filteredAndSortedFiles.map(f => f.path);
        if (selectedFiles.length === visiblePaths.length) {
            setSelectedFiles([]);
        } else {
            setSelectedFiles(visiblePaths);
        }
    };

    const formatSize = (bytes: number): string => {
        if (bytes === 0) return '0 B';
        const k = 1024;
        const sizes = ['B', 'KB', 'MB', 'GB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];
    };

    const formatDate = (dateString: string): string => {
        const date = new Date(dateString);
        const now = new Date();
        const diffMs = now.getTime() - date.getTime();
        const diffMins = Math.floor(diffMs / 60000);
        const diffHours = Math.floor(diffMs / 3600000);
        const diffDays = Math.floor(diffMs / 86400000);

        if (diffMins < 1) return 'Just now';
        if (diffMins < 60) return `${diffMins}m ago`;
        if (diffHours < 24) return `${diffHours}h ago`;
        if (diffDays < 7) return `${diffDays}d ago`;
        return date.toLocaleDateString();
    };

    const isRecentlyDeleted = (dateString: string): boolean => {
        const date = new Date(dateString);
        const now = new Date();
        return now.getTime() - date.getTime() < 3600000;
    };

    const formatCountdown = (ms: number): string => {
        const totalMinutes = Math.max(0, Math.ceil(ms / 60000));
        const days = Math.floor(totalMinutes / 1440);
        const hours = Math.floor((totalMinutes % 1440) / 60);
        const minutes = totalMinutes % 60;

        if (days > 0) return `${days}d ${hours}h`;
        if (hours > 0) return `${hours}h ${minutes}m`;
        return `${minutes}m`;
    };

    const getDeletionCountdown = (file: TrashFile): { label: string; urgent: boolean } | null => {
        if (!cleanupSettings) return null;
        if (!cleanupSettings.global_enabled || !cleanupSettings.trash_cleanup_enabled) {
            return { label: 'Auto-cleanup off', urgent: false };
        }

        const deletedAt = new Date(file.deletedAt).getTime();
        if (Number.isNaN(deletedAt)) return null;

        const retentionValue = Math.max(1, cleanupSettings.trash_retention_days || 1);
        const retentionMs =
            cleanupSettings.trash_retention_unit === 'hours'
                ? retentionValue * 3600000
                : retentionValue * 86400000;

        const expiresAt = deletedAt + retentionMs;
        const remainingMs = expiresAt - Date.now();

        if (remainingMs <= 0) {
            return { label: 'Eligible now', urgent: true };
        }

        return {
            label: `Auto-delete in ${formatCountdown(remainingMs)}`,
            urgent: remainingMs <= 3600000,
        };
    };

    const getTotalSize = (): number => {
        return trashFiles.reduce((acc, file) => acc + file.size, 0);
    };

    const filteredAndSortedFiles = React.useMemo(() => {
        let filtered = trashFiles;

        if (searchQuery) {
            const query = searchQuery.toLowerCase();
            filtered = trashFiles.filter(file =>
                file.name.toLowerCase().includes(query) ||
                file.originalPath.toLowerCase().includes(query)
            );
        }

        return filtered.sort((a, b) => {
            let comparison = 0;
            switch (sortBy) {
                case 'name':
                    comparison = a.name.localeCompare(b.name);
                    break;
                case 'size':
                    comparison = a.size - b.size;
                    break;
                case 'date':
                default:
                    comparison = new Date(b.deletedAt).getTime() - new Date(a.deletedAt).getTime();
                    break;
            }
            return sortDirection === 'asc' ? comparison : -comparison;
        });
    }, [trashFiles, searchQuery, sortBy, sortDirection]);

    const toggleSort = (newSortBy: 'date' | 'name' | 'size') => {
        if (sortBy === newSortBy) {
            setSortDirection(prev => prev === 'asc' ? 'desc' : 'asc');
        } else {
            setSortBy(newSortBy);
            setSortDirection(newSortBy === 'date' ? 'desc' : 'asc');
        }
    };

    return (
        <>
            <Dialog
                open={visible && !showEmptyConfirm}
                onClose={onDismiss}
                title='Trash Bin'
            >
                {loading && trashFiles.length === 0 ? (
                    <div className='py-16 flex justify-center'>
                        <Spinner size='large' />
                    </div>
                ) : trashFiles.length === 0 ? (
                    <div className='text-center py-16'>
                        <div className='w-24 h-24 mx-auto mb-6 rounded-full bg-neutral-600 flex items-center justify-center'>
                            <svg className='w-12 h-12 text-neutral-400' fill='none' stroke='currentColor' viewBox='0 0 24 24'>
                                <path strokeLinecap='round' strokeLinejoin='round' strokeWidth={1.5} d='M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16' />
                            </svg>
                        </div>
                        <p className='text-lg font-semibold text-neutral-200 mb-2'>Trash is empty</p>
                        <p className='text-sm text-neutral-400'>
                            Files you delete will appear here for easy recovery.
                        </p>
                    </div>
                ) : (
                    <>
                        <div className='flex items-center justify-between mb-4 pb-4 border-b border-neutral-700'>
                            <div className='flex items-center gap-3'>
                                <span className='inline-flex items-center gap-1.5 px-2.5 py-1 rounded text-xs font-medium bg-neutral-600 text-neutral-200'>
                                    <svg className='w-3.5 h-3.5' fill='none' stroke='currentColor' viewBox='0 0 24 24'>
                                        <path strokeLinecap='round' strokeLinejoin='round' strokeWidth={2} d='M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z' />
                                    </svg>
                                    {trashFiles.length} {trashFiles.length === 1 ? 'item' : 'items'}
                                </span>
                                <span className='inline-flex items-center gap-1.5 px-2.5 py-1 rounded text-xs font-medium bg-neutral-600 text-neutral-200'>
                                    <svg className='w-3.5 h-3.5' fill='none' stroke='currentColor' viewBox='0 0 24 24'>
                                        <path strokeLinecap='round' strokeLinejoin='round' strokeWidth={2} d='M4 7v10c0 2 1 3 3 3h10c2 0 3-1 3-3V7' />
                                    </svg>
                                    {formatSize(getTotalSize())}
                                </span>
                            </div>
                            <button
                                onClick={selectAllVisible}
                                className='flex items-center gap-1.5 text-xs text-neutral-400 hover:text-neutral-200 transition-colors'
                            >
                                <svg className='w-4 h-4' fill='none' stroke='currentColor' viewBox='0 0 24 24'>
                                    <path strokeLinecap='round' strokeLinejoin='round' strokeWidth={2} d='M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2' />
                                </svg>
                                {selectedFiles.length === filteredAndSortedFiles.length ? 'Deselect All' : 'Select All'}
                            </button>
                        </div>

                        <div className='mb-4'>
                            <Input
                                type='text'
                                placeholder='Search deleted files...'
                                value={searchQuery}
                                onChange={(e: React.ChangeEvent<HTMLInputElement>) => setSearchQuery(e.target.value)}
                            />
                        </div>

                        <div className='flex gap-2 mb-4'>
                            {(['date', 'name', 'size'] as const).map((sort) => (
                                <button
                                    key={sort}
                                    onClick={() => toggleSort(sort)}
                                    className={cx(
                                        'px-3 py-1.5 rounded text-xs font-medium border transition-colors',
                                        sortBy === sort
                                            ? 'bg-neutral-600 border-neutral-500 text-neutral-100'
                                            : 'bg-neutral-700 border-neutral-600 text-neutral-400 hover:text-neutral-200'
                                    )}
                                >
                                    {sort.charAt(0).toUpperCase() + sort.slice(1)}
                                    {sortBy === sort && (
                                        <span className='ml-1'>{sortDirection === 'asc' ? '↑' : '↓'}</span>
                                    )}
                                </button>
                            ))}
                        </div>

                        <div className='max-h-96 overflow-y-auto space-y-2'>
                            {filteredAndSortedFiles.length === 0 ? (
                                <div className='text-center py-8 text-neutral-400 text-sm'>
                                    No files match your search
                                </div>
                            ) : (
                                filteredAndSortedFiles.map((file) => {
                                    const countdown = getDeletionCountdown(file);
                                    const isSelected = selectedFiles.includes(file.path);
                                    return (
                                        <GreyRowBox
                                            key={file.path}
                                            className={cx(
                                                'cursor-pointer',
                                                isSelected && 'border-neutral-500'
                                            )}
                                            onClick={() => toggleFileSelection(file.path)}
                                        >
                                            <Input
                                                type='checkbox'
                                                checked={isSelected}
                                                onChange={() => {}}
                                                onClick={(e: React.MouseEvent) => e.stopPropagation()}
                                                className='mr-3 flex-shrink-0'
                                            />
                                            <div className={cx(
                                                'w-10 h-10 rounded flex items-center justify-center mr-3 flex-shrink-0',
                                                file.isFile ? 'bg-neutral-600' : 'bg-neutral-600'
                                            )}>
                                                {file.isFile ? (
                                                    <svg className='w-4 h-4 text-neutral-300' fill='none' stroke='currentColor' viewBox='0 0 24 24'>
                                                        <path strokeLinecap='round' strokeLinejoin='round' strokeWidth={2} d='M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z' />
                                                    </svg>
                                                ) : (
                                                    <svg className='w-4 h-4 text-neutral-300' fill='none' stroke='currentColor' viewBox='0 0 24 24'>
                                                        <path strokeLinecap='round' strokeLinejoin='round' strokeWidth={2} d='M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z' />
                                                    </svg>
                                                )}
                                            </div>
                                            <div className='flex-1 min-w-0'>
                                                <p className='text-sm font-medium text-neutral-200 truncate'>{file.name}</p>
                                                <p className='text-xs text-neutral-500 truncate' title={file.originalPath}>
                                                    From: {file.originalPath}
                                                </p>
                                                <div className='flex items-center gap-2 mt-1 flex-wrap'>
                                                    <span className='text-xs text-neutral-500'>{formatSize(file.size)}</span>
                                                    <span className={cx(
                                                        'text-xs',
                                                        isRecentlyDeleted(file.deletedAt) ? 'text-yellow-400' : 'text-neutral-500'
                                                    )}>
                                                        {isRecentlyDeleted(file.deletedAt) && '• '}
                                                        {formatDate(file.deletedAt)}
                                                    </span>
                                                    {countdown && (
                                                        <span className={cx(
                                                            'text-xs',
                                                            countdown.urgent ? 'text-red-400' : 'text-neutral-500'
                                                        )}>
                                                            {countdown.label}
                                                        </span>
                                                    )}
                                                </div>
                                            </div>
                                        </GreyRowBox>
                                    );
                                })
                            )}
                        </div>

                        <Dialog.Footer>
                            <Button
                                onClick={handleRestore}
                                disabled={selectedFiles.length === 0 || loading}
                            >
                                {loading ? (
                                    <Spinner size='small' />
                                ) : (
                                    <>
                                        <svg className='w-4 h-4 mr-2' fill='none' stroke='currentColor' viewBox='0 0 24 24'>
                                            <path strokeLinecap='round' strokeLinejoin='round' strokeWidth={2} d='M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15' />
                                        </svg>
                                        Restore ({selectedFiles.length})
                                    </>
                                )}
                            </Button>
                            <Button.Danger
                                onClick={() => setShowEmptyConfirm(true)}
                                disabled={loading || trashFiles.length === 0}
                            >
                                <svg className='w-4 h-4 mr-2' fill='none' stroke='currentColor' viewBox='0 0 24 24'>
                                    <path strokeLinecap='round' strokeLinejoin='round' strokeWidth={2} d='M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16' />
                                </svg>
                                Empty All
                            </Button.Danger>
                        </Dialog.Footer>
                    </>
                )}
            </Dialog>

            <Dialog.Confirm
                open={visible && showEmptyConfirm}
                onClose={() => setShowEmptyConfirm(false)}
                title='Empty Trash?'
                confirm='Yes, Empty Trash'
                onConfirmed={handleEmptyTrash}
            >
                <Dialog.Icon type='danger' position='title' />
                <p className='text-sm text-neutral-300'>
                    This will permanently delete {trashFiles.length} {trashFiles.length === 1 ? 'item' : 'items'} ({formatSize(getTotalSize())}).
                </p>
                <p className='text-sm text-red-400 mt-2'>This action cannot be undone.</p>
            </Dialog.Confirm>
        </>
    );
};

export default TrashBinModal;
