import React, { useMemo } from 'react';
import { createPortal } from 'react-dom';
import GreyRowBox from '@/components/elements/GreyRowBox';
import { Button } from '@/components/elements/button/index';
import type { UploadProgress } from './uploadUtils';

interface Props {
    uploads: Map<string, UploadProgress>;
    showUploadModal: boolean;
    setShowUploadModal: (next: boolean) => void;
    cancelAllUploads: () => void;
    cancelUpload: (key: string) => void;
    clearFinishedUploads: () => void;
    clearUpload: (key: string) => void;
    formatBytes: (value: number) => string;
}

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

const getUploadPortalRoot = (): HTMLElement | null => {
    if (typeof document === 'undefined') return null;
    let root = document.getElementById('bfm-upload-portal-root');
    if (!root) {
        root = document.createElement('div');
        root.id = 'bfm-upload-portal-root';
        root.style.position = 'fixed';
        root.style.inset = '0';
        root.style.zIndex = '2147483647';
        root.style.display = 'flex';
        root.style.alignItems = 'flex-end';
        root.style.justifyContent = 'flex-end';
        root.style.padding = '24px';
        root.style.boxSizing = 'border-box';
        root.style.pointerEvents = 'none';
        root.style.isolation = 'isolate';
        document.documentElement.appendChild(root);
    }
    return root;
};

const getProgress = (upload: UploadProgress) => {
    if (upload.total <= 0) return upload.status === 'completed' ? 100 : 0;
    return Math.min(100, Math.max(0, Math.round((upload.loaded / upload.total) * 100)));
};

const statusClass = (status: UploadProgress['status']) => {
    if (status === 'completed') return 'text-green-400';
    if (status === 'failed') return 'text-red-400';
    if (status === 'canceled') return 'text-yellow-400';
    return 'text-blue-400';
};

const statusLabel = (status: UploadProgress['status']) => {
    if (status === 'completed') return 'Complete';
    if (status === 'failed') return 'Failed';
    if (status === 'canceled') return 'Canceled';
    return 'Uploading';
};

const UploadProgressPanel: React.FC<Props> = ({
    uploads,
    showUploadModal,
    setShowUploadModal,
    cancelAllUploads,
    cancelUpload,
    clearFinishedUploads,
    clearUpload,
    formatBytes,
}) => {
    const portalTarget = useMemo(() => getUploadPortalRoot(), []);
    if (uploads.size === 0) return null;
    const uploadEntries = Array.from(uploads.entries());
    const activeCount = uploadEntries.filter(([, upload]) => upload.status === 'uploading').length;
    const finishedCount = uploadEntries.length - activeCount;
    const title = activeCount > 0
        ? `Uploading ${activeCount} file${activeCount === 1 ? '' : 's'}`
        : `${finishedCount} upload${finishedCount === 1 ? '' : 's'} finished`;

    const content = showUploadModal ? (
        <GreyRowBox
            className='z-[2147483647] !flex-col !items-stretch overflow-hidden border border-neutral-700 shadow-2xl'
            $hoverable={false}
            style={{
                position: 'relative',
                width: 'min(420px, calc(100vw - 16px))',
                maxHeight: 'min(72vh, calc(100vh - 16px))',
                padding: 0,
                pointerEvents: 'auto',
            }}
        >
            <div className='flex items-center justify-between gap-3 border-b border-neutral-700 px-4 py-3'>
                <div className='min-w-0'>
                    <div className='truncate text-sm font-semibold text-neutral-100'>{title}</div>
                    <div className='text-xs text-neutral-400'>{uploadEntries.length} total</div>
                </div>
                <div className='flex shrink-0 items-center gap-2'>
                    {finishedCount > 0 && (
                        <Button.Text type='button' size={Button.Sizes.Small} onClick={clearFinishedUploads}>
                            Clear
                        </Button.Text>
                    )}
                    {activeCount > 0 && (
                        <Button.Danger type='button' size={Button.Sizes.Small} onClick={cancelAllUploads}>
                            Cancel
                        </Button.Danger>
                    )}
                    <Button.Text
                        type='button'
                        size={Button.Sizes.Small}
                        shape={Button.Shapes.IconSquare}
                        onClick={() => setShowUploadModal(false)}
                        title='Hide uploads'
                    >
                        <svg className='h-4 w-4' fill='none' stroke='currentColor' viewBox='0 0 24 24'>
                            <path strokeLinecap='round' strokeLinejoin='round' strokeWidth={2} d='M6 18L18 6M6 6l12 12' />
                        </svg>
                    </Button.Text>
                </div>
            </div>

            <div className='max-h-[52vh] overflow-y-auto'>
                {uploadEntries.map(([key, upload]) => {
                    const progress = getProgress(upload);
                    const isActive = upload.status === 'uploading';

                    return (
                        <div key={key} className='border-b border-neutral-700 px-4 py-3 last:border-b-0'>
                            <div className='flex items-center gap-3'>
                                <div className='min-w-0 flex-1'>
                                    <div className='truncate text-sm font-semibold text-neutral-100' title={upload.name}>
                                        {upload.name}
                                    </div>
                                    <div className='mt-1 truncate text-xs text-neutral-400'>{upload.targetPath}</div>
                                </div>
                                <span className={cx('shrink-0 text-xs font-semibold', statusClass(upload.status))}>
                                    {statusLabel(upload.status)}
                                </span>
                                <Button.Text
                                    type='button'
                                    size={Button.Sizes.Small}
                                    shape={Button.Shapes.IconSquare}
                                    onClick={() => (isActive ? cancelUpload(key) : clearUpload(key))}
                                    title={isActive ? 'Cancel upload' : 'Clear upload'}
                                >
                                    <svg className='h-4 w-4' fill='none' stroke='currentColor' viewBox='0 0 24 24'>
                                        <path strokeLinecap='round' strokeLinejoin='round' strokeWidth={2} d='M6 18L18 6M6 6l12 12' />
                                    </svg>
                                </Button.Text>
                            </div>
                            <div className='mt-3 h-1 overflow-hidden rounded bg-neutral-700'>
                                <div
                                    className={cx(
                                        'h-full min-w-[1px] transition-all duration-300',
                                        upload.status === 'failed' ? 'bg-red-500' :
                                            upload.status === 'canceled' ? 'bg-yellow-500' :
                                                upload.status === 'completed' ? 'bg-green-500' : 'bg-blue-500'
                                    )}
                                    style={{ width: `${progress}%` }}
                                />
                            </div>
                            <div className='mt-2 flex items-center justify-between gap-3 text-xs text-neutral-400'>
                                <span>{progress}%</span>
                                <span>{formatBytes(upload.loaded)} / {formatBytes(upload.total)}</span>
                            </div>
                            {upload.error && (
                                <div className='mt-2 text-xs text-red-400'>{upload.error}</div>
                            )}
                        </div>
                    );
                })}
            </div>
        </GreyRowBox>
    ) : (
        <GreyRowBox
            className='z-[2147483647] cursor-pointer border border-neutral-700 px-4 py-2 shadow-2xl'
            $hoverable={false}
            style={{
                position: 'relative',
                maxWidth: 'calc(100vw - 16px)',
                pointerEvents: 'auto',
            }}
            onClick={() => setShowUploadModal(true)}
            title='Show uploads'
        >
            <span className='text-sm font-semibold text-neutral-100'>{title}</span>
        </GreyRowBox>
    );

    return portalTarget ? createPortal(content, portalTarget) : null;
};

export default UploadProgressPanel;
