import { useDocuments, useDownload, useFolders } from '../hooks/swrHooks'
import { IDocument, IDocumentFolder } from '../interfaces/documents'
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, Stack, Table, Text } from '@mantine/core'
import { IconCancel, IconDownload, IconFile, IconFileFilled, IconFilePlus, IconFileUpload, IconFolderFilled, IconX } from '@tabler/icons-react'

interface DocumentProps {
    doc: IDocument;
}

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

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 }: 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, doc.name])

    return (
        <Flex>
            <ActionIcon
                onClick={(e) => {
                    e.stopPropagation()
                    if (!isLoading) {
                        setShouldFetch(true)
                    }
                }}
                variant='subtle'>
                {isLoading ?
                    <Loader size='sm' />
                    :
                    <IconDownload />
                }
            </ActionIcon>
        </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'}>
            {fileViewerModal &&
                <FileViewer
                    open={fileViewerModal}
                    setOpen={setFileViewerModal}
                    currentFileNo={currentFileNo}
                    setCurrentFileNo={setCurrentFileNo}
                    docs={documents}
                />
            }


            <Stack>
                <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.Th>Название</Table.Th>
                            <Table.Th p={0}>Дата создания</Table.Th>
                            <Table.Th p={0}></Table.Th>
                        </Table.Tr>
                    </Table.Thead>

                    <Table.Tbody>
                        {currentFolder ? (
                            documents?.map((doc: IDocument, index: number) => (
                                <Table.Tr key={doc.id} onClick={() => handleDocumentClick(index)} style={{ cursor: 'pointer' }}>
                                    <Table.Td p={0}>
                                        <Flex style={FileItemStyle}>
                                            <IconFileFilled />
                                            {doc.name}
                                        </Flex>
                                    </Table.Td>
                                    <Table.Td p={0}>
                                        {new Date(doc.create_date).toLocaleDateString()}
                                    </Table.Td>
                                    <Table.Td p={0}>
                                        <ItemDocument
                                            doc={doc}
                                        />
                                    </Table.Td>
                                </Table.Tr>
                            ))
                        ) : (
                            folders?.map((folder: IDocumentFolder) => (
                                <Table.Tr key={folder.id} onClick={() => handleFolderClick(folder)} style={{ cursor: 'pointer' }}>
                                    <Table.Td p={0}>
                                        <Flex style={FileItemStyle}>
                                            <IconFolderFilled />
                                            {folder.name}
                                        </Flex>
                                    </Table.Td>
                                    <Table.Td p={0} align='left'>
                                        {new Date(folder.create_date).toLocaleDateString()}
                                    </Table.Td>
                                    <Table.Td p={0}>
                                    </Table.Td>
                                </Table.Tr>
                            ))
                        )}
                    </Table.Tbody>
                </Table>
            </Stack>
        </ScrollAreaAutosize>
    )
}