'use client'

import { useState } from 'react';
import { Dropzone, MIME_TYPES, FileRejection } from '@mantine/dropzone';
import { Button, Box, Text, Stack, Group, ActionIcon, Paper, Alert } from '@pikku/mantine/core';
import { IconX, IconPlus } from '@tabler/icons-react';
import { useI18n } from '@/context/i18n-provider';
import { asI18n } from '@pikku/react';

type UploadedFile = {
    id: string
    fileName: string
}

export type UploadFile = (files: File[]) => Promise<void>
export type DeleteFile = (id: string) => Promise<void>

interface FileUploadProps {
    multiple?: boolean;
    accept?: string;
    maxFileSize?: number;
    chooseLabel?: string;
    className?: string;
    files: UploadedFile[]
    uploadFiles: UploadFile
    deleteFile: DeleteFile
}

export const FileUpload: React.FunctionComponent<FileUploadProps> = ({
    multiple = true,
    accept = ".pdf,.jpg,.jpeg,.png",
    maxFileSize = 210000000,
    chooseLabel,
    files = [],
    uploadFiles,
    deleteFile
}) => {
    const t = useI18n()
    const [uploading, setUploading] = useState(false);
    const [rejectionError, setRejectionError] = useState<string | null>(null);

    const defaultChooseLabel = chooseLabel ? asI18n(chooseLabel) : t('jobs.fileupload.choosefile')

    const handleUpload = async (files: File[]) => {
        setRejectionError(null); // Clear any previous errors
        setUploading(true);
        try {
            await uploadFiles(files)
        } catch (error) {
            console.error('Error uploading files:', error)
        }
        setUploading(false);
    }

    const handleReject = (rejectedFiles: FileRejection[]) => {
        if (rejectedFiles.length > 0) {
            const firstError = rejectedFiles[0].errors[0];
            let errorMessage: string;

            switch (firstError.code) {
                case 'file-invalid-type':
                    errorMessage = t('jobs.fileupload.error.file-invalid-type');
                    break;
                case 'file-too-large':
                    errorMessage = t('jobs.fileupload.error.file-too-large');
                    break;
                case 'file-too-small':
                    errorMessage = t('jobs.fileupload.error.file-too-small');
                    break;
                case 'too-many-files':
                    errorMessage = t('jobs.fileupload.error.too-many-files');
                    break;
                default:
                    errorMessage = firstError.message;
            }

            setRejectionError(errorMessage);
        }
    }

    const handleDelete = async (file: UploadedFile) => {
        try {
            await deleteFile(file.id)
        } catch (error) {
            console.error('Error deleting file:', error)
        }
    }

    const acceptTypes = accept.split(',').map(type => {
        switch (type.trim()) {
            case '.pdf': return MIME_TYPES.pdf;
            case '.jpg':
            case '.jpeg': return MIME_TYPES.jpeg;
            case '.png': return MIME_TYPES.png;
            default: return type.trim();
        }
    });

    return (
        <Paper p="xl" withBorder>
            <Box pos="relative">
                <Dropzone
                    multiple={multiple}
                    accept={acceptTypes}
                    maxSize={maxFileSize}
                    onDrop={handleUpload}
                    onReject={handleReject}
                    loading={uploading}
                    bd='none'
                    bg='transparent'
                    p={0}
                >
                    <Stack gap="md">
                        <Button
                            size="md"
                            loading={uploading}
                            leftSection={<IconPlus size={16} />}
                        >
                            {defaultChooseLabel}
                        </Button>
                        {!files || files.length === 0 ? (
                            <Stack gap="xs">
                                <Text size="md" fw={500}>{t('jobs.fileupload.dragdroptext')}</Text>
                                <Text size="sm" c="dimmed">
                                    {t('jobs.fileupload.acceptedformats')}
                                    <br />
                                    {t('jobs.fileupload.maxsize')}
                                </Text>
                            </Stack>
                        ) : null}
                    </Stack>
                </Dropzone>
            </Box>

            {files && files.length > 0 && (
                <Stack gap="sm" mt="md">
                    {files.map((file) => (
                        <Group key={file.id} justify="space-between" align="center">
                            <Text
                                fw={500}
                                c="dark"
                                maw={250}
                                style={{
                                    overflow: 'hidden',
                                    textOverflow: 'ellipsis',
                                    whiteSpace: 'nowrap',
                                }}
                            >
                                {asI18n(file.fileName)}
                            </Text>
                            <ActionIcon
                                variant="subtle"
                                color="red"
                                size="sm"
                                onClick={() => handleDelete(file)}
                                aria-label={t('jobs.fileupload.delete')}
                            >
                                <IconX size={16} />
                            </ActionIcon>
                        </Group>
                    ))}
                </Stack>
            )}

            {rejectionError && (
                <Alert color="red" mt="md" onClose={() => setRejectionError(null)} withCloseButton>
                    {asI18n(rejectionError)}
                </Alert>
            )}
        </Paper>
    );
}
