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 { IconCancel, IconDownload, IconFileUpload, IconX } from '@tabler/icons-react'
import { Breadcrumb, BreadcrumbButton, BreadcrumbDivider, BreadcrumbItem, Button, createTableColumn, DataGrid, DataGridBody, DataGridCell, DataGridHeader, DataGridHeaderCell, DataGridRow, Divider, Field, ProgressBar, Spinner, TableCellLayout } from '@fluentui/react-components'
import { DocumentAdd20Regular, DocumentColor, DocumentRegular, DocumentTextColor, FolderRegular, ImageColor, TableColor } from '@fluentui/react-icons'

interface DocumentProps {
    doc: IDocument;
}

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 getFileExtension(filename: string): string {
    return filename.split('.').pop()?.toLowerCase() || '';
}

function handleDocFormatIcon(docName: string) {
    const ext = getFileExtension(docName);

    switch (ext) {
        case 'docx':
            return <DocumentTextColor />
        case 'pdf':
            return <DocumentTextColor color='red' />
        case 'xlsx':
            return <TableColor />
        case 'jpg':
            return <ImageColor />
        default:
            return <DocumentRegular />
    }
}

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 (
        <Button icon={isLoading ?
            <Spinner size='tiny' />
            :
            <IconDownload />
        } appearance='subtle' onClick={(e) => {
            e.stopPropagation()
            if (!isLoading) {
                setShouldFetch(true)
            }
        }} />
    )
}

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);
            }
        }
    }

    const fileInputRef = React.useRef<HTMLInputElement | null>(null);

    const handleClick = () => {
        fileInputRef.current?.click();
    };

    const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        if (e.target.files) {
            handleFileInput(Array.from(e.target.files))
        }
    };

    if (foldersLoading || documentsLoading) {
        return (
            <div style={{
                display: 'flex',
                justifyContent: 'center',
                alignItems: 'center',
                width: '100%',
                height: '100%',
                padding: '1rem',
            }}>
                <Spinner />
            </div>
        )
    }

    return (
        <div style={{
            width: '100%',
            height: '100%',
            padding: '1rem',
        }}>
            {fileViewerModal &&
                <FileViewer
                    open={fileViewerModal}
                    setOpen={setFileViewerModal}
                    currentFileNo={currentFileNo}
                    setCurrentFileNo={setCurrentFileNo}
                    docs={documents}
                />
            }

            <div style={{
                display: 'flex',
                flexDirection: 'column',
                height: '100%',
                width: '100%',
                gap: '1rem'
            }}>
                <Breadcrumb>
                    <BreadcrumbItem>
                        <BreadcrumbButton onClick={() => {
                            setCurrentFolder(null)
                            setBreadcrumbs([])
                        }}>Главная</BreadcrumbButton>
                    </BreadcrumbItem>

                    {breadcrumbs.map((breadcrumb, index) => (
                        <>
                            <BreadcrumbDivider />
                            <BreadcrumbItem key={breadcrumb.id}>
                                <BreadcrumbButton icon={<FolderRegular />} onClick={() => {
                                    handleBreadcrumbClick(index)
                                }}>{breadcrumb.name}</BreadcrumbButton>
                            </BreadcrumbItem>
                        </>

                    ))}
                </Breadcrumb>

                {currentFolder &&
                    <div style={{
                        display: 'flex',
                        flexDirection: 'column',
                        gap: '1rem'
                    }}>
                        <div style={{
                            display: 'flex',
                            flexDirection: 'column',
                            gap: '1rem',
                            padding: '1rem',
                            border: filesToUpload.length > 0 ? '1px dashed gray' : 'none',
                            borderRadius: '8px',
                        }}>
                            <div style={{ display: 'flex', gap: '1rem' }}>
                                <input
                                    type="file"
                                    multiple
                                    ref={fileInputRef}
                                    style={{ display: "none" }}
                                    onChange={handleFileChange}
                                />
                                <Button appearance="primary" icon={<DocumentAdd20Regular />} onClick={handleClick}>
                                    Добавить
                                </Button>

                                {filesToUpload.length > 0 &&
                                    <>
                                        <Button
                                            appearance='primary'
                                            icon={<IconFileUpload />}
                                            onClick={uploadFiles}
                                            disabled={isUploading}
                                        >
                                            Загрузить все
                                        </Button>

                                        <Button
                                            appearance='outline'
                                            icon={<IconCancel />}
                                            onClick={() => {
                                                setFilesToUpload([])
                                            }}
                                        >
                                            Отмена
                                        </Button>
                                    </>
                                }
                            </div>

                            {isUploading &&
                                <Field validationMessage={"Загрузка файлов..."} validationState='none'>
                                    <ProgressBar value={uploadProgress} />
                                </Field>
                            }

                            <Divider />

                            {filesToUpload.length > 0 &&
                                <div style={{
                                    display: 'flex',
                                    flexDirection: 'column'
                                }}>
                                    {filesToUpload.map((file, index) => (
                                        <div style={{
                                            display: 'flex',
                                        }} key={index}>
                                            <Button appearance='transparent' icon={<DocumentColor />}>
                                                {file.name}
                                            </Button>

                                            <Button style={{ marginLeft: 'auto' }} appearance='subtle' icon={<IconX />} onClick={() => {
                                                setFilesToUpload(prev => {
                                                    return prev.filter((_, i) => i != index)
                                                })
                                            }} />
                                        </div>
                                    ))}
                                </div>
                            }
                        </div>
                    </div>
                }

                <div style={{
                    width: '100%',
                    overflow: 'auto'
                }}>
                    <DataGrid
                        onDragOver={handleDragOver}
                        onDragLeave={handleDragLeave}
                        onDrop={handleDrop}
                        style={{ backgroundColor: dragOver ? 'rgba(0, 0, 0, 0.1)' : 'inherit' }}
                        items={currentFolder
                            ? (documents ?? []).map((doc: IDocument) => ({ kind: "doc", data: doc }))
                            : (folders ?? []).map((folder: IDocumentFolder) => ({ kind: "folder", data: folder }))}
                        columns={[
                            createTableColumn({
                                columnId: "name",
                                renderHeaderCell: () => "Название",
                                renderCell: (item) => (
                                    <TableCellLayout truncate media={item.kind === "doc" ? handleDocFormatIcon(item.data.name) : <FolderRegular />}>
                                        {item.data.name}
                                    </TableCellLayout>
                                ),
                            }),
                            createTableColumn({
                                columnId: "date",
                                renderHeaderCell: () => "Дата создания",
                                renderCell: (item) =>
                                    new Date(item.data.create_date).toLocaleDateString(),
                            }),
                            createTableColumn({
                                columnId: "actions",
                                renderHeaderCell: () => "",
                                renderCell: (item) => {
                                    if (item.kind === "doc") {
                                        // replace with your <ItemDocument doc={doc} />
                                        return <ItemDocument doc={item.data} />;
                                    }
                                    return null;
                                },
                            }),
                        ]}
                        focusMode="cell"
                        resizableColumns
                        getRowId={(item) => item.data.id}
                    >
                        <DataGridHeader>
                            <DataGridRow>
                                {({ renderHeaderCell }) => (
                                    <DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>
                                )}
                            </DataGridRow>
                        </DataGridHeader>
                        <DataGridBody>
                            {({ item, rowId }: { item: { kind: string, data: any }, rowId: any }) => (
                                <DataGridRow
                                    key={rowId}
                                    style={{ cursor: "pointer" }}
                                    onClick={() => {
                                        if (item.kind === "doc") {
                                            const index = documents?.findIndex((d: any) => d.id === item.data.id) ?? -1;
                                            handleDocumentClick(index);
                                        } else {
                                            handleFolderClick(item.data as IDocumentFolder);
                                        }
                                    }}
                                >
                                    {({ renderCell }) => <DataGridCell>{renderCell(item)}</DataGridCell>}
                                </DataGridRow>
                            )}
                        </DataGridBody>
                    </DataGrid>
                </div>
            </div>
        </div>
    )
}