import { useDocuments, useDownload, useFolders } from '../hooks/swrHooks'
import { IDocument, IDocumentFolder } from '../interfaces/documents'
import { Folder, InsertDriveFile } from '@mui/icons-material'
import React, { useEffect, useState } from 'react'
import DocumentService from '../services/DocumentService'
import { mutate } from 'swr'
import FileViewer from './modals/FileViewer'
import { ActionIcon, Anchor, Breadcrumbs, Button, Divider, FileButton, Flex, Loader, MantineStyleProp, RingProgress, ScrollAreaAutosize, Table, Text } from '@mantine/core'
import { IconCancel, IconDownload, IconFile, IconFilePlus, IconFileUpload, IconX } from '@tabler/icons-react'

interface FolderProps {
    folder: IDocumentFolder;
    index: number;
    handleFolderClick: (folder: IDocumentFolder) => void;
}

interface DocumentProps {
    doc: IDocument;
    index: number;
    handleDocumentClick: (index: number) => void;
}

const FileItemStyle: MantineStyleProp = {
    cursor: 'pointer',
    display: 'flex',
    width: '100%',
    flexDirection: 'row',
    gap: '8px',
    alignItems: 'center',
    padding: '8px'
}

function ItemFolder({ folder, handleFolderClick, ...props }: FolderProps) {
    return (
        <Flex
            onClick={() => handleFolderClick(folder)}
        >
            <Flex
                style={FileItemStyle}
                {...props}
            >
                <Folder />
                {folder.name}
            </Flex>
        </Flex>
    )
}

const handleSave = async (file: Blob, filename: string) => {
    const link = document.createElement('a')
    link.href = window.URL.createObjectURL(file)
    link.download = filename
    link.click()
    link.remove()
    window.URL.revokeObjectURL(link.href)
}

function ItemDocument({ doc, index, handleDocumentClick, ...props }: DocumentProps) {
    const [shouldFetch, setShouldFetch] = useState(false)

    const { file, isLoading } = useDownload(shouldFetch ? doc?.document_folder_id : null, shouldFetch ? doc?.id : null)

    useEffect(() => {
        if (shouldFetch) {
            if (file) {
                handleSave(file, doc.name)
                setShouldFetch(false)
            }
        }
    }, [shouldFetch, file])

    return (
        <Flex align='center'>
            <Flex
                style={FileItemStyle}
                onClick={() => handleDocumentClick(index)}
                {...props}
            >
                <InsertDriveFile />
                {doc.name}
            </Flex>
            <Flex>
                <ActionIcon
                    onClick={() => {
                        if (!isLoading) {
                            setShouldFetch(true)
                        }
                    }}
                    variant='subtle'>
                    {isLoading ?
                        <Loader size='sm' />
                        :
                        <IconDownload />
                    }
                </ActionIcon>
            </Flex>
        </Flex>
    )
}

export default function FolderViewer() {
    const [currentFolder, setCurrentFolder] = useState<IDocumentFolder | null>(null)
    const [breadcrumbs, setBreadcrumbs] = useState<IDocumentFolder[]>([])
    const { folders, isLoading: foldersLoading } = useFolders()
    const { documents, isLoading: documentsLoading } = useDocuments(currentFolder?.id)
    const [uploadProgress, setUploadProgress] = useState(0)
    const [isUploading, setIsUploading] = useState(false)
    const [fileViewerModal, setFileViewerModal] = useState(false)
    const [currentFileNo, setCurrentFileNo] = useState<number>(-1)

    const [dragOver, setDragOver] = useState(false)
    const [filesToUpload, setFilesToUpload] = useState<File[]>([])

    const handleFolderClick = (folder: IDocumentFolder) => {
        setCurrentFolder(folder)
        setBreadcrumbs((prev) => [...prev, folder])
    }

    const handleDocumentClick = async (index: number) => {
        setCurrentFileNo(index)
        setFileViewerModal(true)
    }

    const handleBreadcrumbClick = (index: number) => {
        const newBreadcrumbs = breadcrumbs.slice(0, index + 1);
        setBreadcrumbs(newBreadcrumbs)
        setCurrentFolder(newBreadcrumbs[newBreadcrumbs.length - 1])
    }

    const handleDragOver = (e: React.DragEvent) => {
        e.preventDefault()
        setDragOver(true)
    }

    const handleDragLeave = () => {
        setDragOver(false)
    }

    const handleDrop = (e: React.DragEvent) => {
        e.preventDefault()
        setDragOver(false)
        const files = Array.from(e.dataTransfer.files)
        setFilesToUpload((prevFiles) => [...prevFiles, ...files])
    }

    const handleFileInput = (files: File[] | null) => {
        if (files !== null) {
            setFilesToUpload((prevFiles) => [...prevFiles, ...files])
        }
    }

    const uploadFiles = async () => {
        setIsUploading(true)
        if (filesToUpload.length > 0 && currentFolder && currentFolder.id) {
            const formData = new FormData()
            for (const file of filesToUpload) {
                formData.append('files', file)
            }
            try {
                await DocumentService.uploadFiles(currentFolder.id, formData, setUploadProgress);
                setIsUploading(false);
                setFilesToUpload([]);
                mutate(`/info/documents/${currentFolder.id}`);
            } catch (error) {
                console.error(error);
                setIsUploading(false);
            }
        }
    }

    if (foldersLoading || documentsLoading) {
        return (
            <Loader />
        )
    }

    return (
        <ScrollAreaAutosize w={'100%'} h={'100%'} p={'sm'}>
            <FileViewer
                open={fileViewerModal}
                setOpen={setFileViewerModal}
                currentFileNo={currentFileNo}
                setCurrentFileNo={setCurrentFileNo}
                docs={documents}
            />

            <Breadcrumbs>
                <Anchor
                    onClick={() => {
                        setCurrentFolder(null)
                        setBreadcrumbs([])
                    }}
                >
                    Главная
                </Anchor>
                {breadcrumbs.map((breadcrumb, index) => (
                    <Anchor
                        key={breadcrumb.id}
                        onClick={() => handleBreadcrumbClick(index)}
                    >
                        {breadcrumb.name}
                    </Anchor>
                ))}
            </Breadcrumbs>

            {currentFolder &&
                <Flex direction='column' gap='sm'>
                    <Flex direction='column' gap='sm' p='sm' style={{
                        border: filesToUpload.length > 0 ? '1px dashed gray' : 'none',
                        borderRadius: '8px',
                    }}>
                        <Flex gap='sm'>
                            <FileButton multiple onChange={handleFileInput}>
                                {(props) => <Button variant='filled' leftSection={isUploading ? <Loader /> : <IconFilePlus />} {...props}>Добавить</Button>}
                            </FileButton>

                            {filesToUpload.length > 0 &&
                                <>
                                    <Button
                                        variant='filled'
                                        leftSection={isUploading ? <RingProgress sections={[{ value: uploadProgress, color: 'blue' }]} /> : <IconFileUpload />}
                                        onClick={uploadFiles}
                                    >
                                        Загрузить все
                                    </Button>

                                    <Button
                                        variant='outline'
                                        leftSection={<IconCancel />}
                                        onClick={() => {
                                            setFilesToUpload([])
                                        }}
                                    >
                                        Отмена
                                    </Button>
                                </>
                            }
                        </Flex>

                        <Divider />

                        {filesToUpload.length > 0 &&
                            <Flex direction='column'>
                                {filesToUpload.map((file, index) => (
                                    <Flex key={index} p='8px'>
                                        <Flex gap='sm' direction='row' align='center'>
                                            <IconFile />
                                            <Text>{file.name}</Text>
                                        </Flex>

                                        <ActionIcon onClick={() => {
                                            setFilesToUpload(prev => {
                                                return prev.filter((_, i) => i != index)
                                            })
                                        }} ml='auto' variant='subtle'>
                                            <IconX />
                                        </ActionIcon>
                                    </Flex>
                                ))}
                            </Flex>
                        }
                    </Flex>
                </Flex>
            }

            <Table
                onDragOver={handleDragOver}
                onDragLeave={handleDragLeave}
                onDrop={handleDrop}
                bg={dragOver ? 'rgba(0, 0, 0, 0.1)' : 'inherit'}
                highlightOnHover>
                <Table.Thead>
                    <Table.Tr>

                    </Table.Tr>
                </Table.Thead>

                <Table.Tbody>
                    {currentFolder ? (
                        documents?.map((doc: IDocument, index: number) => (
                            <Table.Tr key={doc.id}>
                                <Table.Td>
                                    <ItemDocument
                                        doc={doc}
                                        index={index}
                                        handleDocumentClick={handleDocumentClick}
                                    />
                                </Table.Td>
                            </Table.Tr>
                        ))
                    ) : (
                        folders?.map((folder: IDocumentFolder, index: number) => (
                            <Table.Tr key={folder.id}>
                                <Table.Td>
                                    <ItemFolder
                                        folder={folder}
                                        index={index}
                                        handleFolderClick={handleFolderClick}
                                    />
                                </Table.Td>
                            </Table.Tr>
                        ))
                    )}
                </Table.Tbody>
            </Table>
        </ScrollAreaAutosize>
    )
}