'use client';

import { Button } from '@/ui/components/shadcn/button';
import {
    Field,
    FieldDescription,
    FieldError,
} from '@/ui/components/shadcn/field';
import {
    FileUpload,
    FileUploadDropzone,
    FileUploadItem,
    FileUploadItemDelete,
    FileUploadItemMetadata,
    FileUploadItemPreview,
    FileUploadList,
    FileUploadTrigger,
} from '@/ui/components/shadcn/file-upload';
import { Spinner } from '@/ui/components/shadcn/spinner';
import { X } from 'lucide-react';
import React, { useCallback } from 'react';

export interface FileUploadFieldProps {
    file: File | null;
    onFileChange: (file: File | null) => Promise<void>;
    accept?: string;
    validate?: (file: File) => string | null;
    onFileReject?: (file: File, message: string) => void;
    label?: string;
    description?: string;
    error?: string;
    icon?: React.ReactNode;
    previewUrl?: string;
    isUploading?: boolean;
}

export const FileUploadField: React.FC<FileUploadFieldProps> = ({
    file,
    onFileChange,
    accept,
    validate,
    onFileReject,
    label = 'File',
    description,
    error,
    icon,
    previewUrl,
    isUploading,
}) => {
    const handleAccept = useCallback(
        (files: File[]) => {
            const accepted = files[0];
            if (!accepted) return;
            onFileChange(accepted).then(() => {});
        },
        [onFileChange]
    );

    const handleValueChange = useCallback(
        (files: File[]) => {
            if (files.length === 0) onFileChange(null);
        },
        [onFileChange]
    );

    return (
        <Field data-invalid={!!error}>
            <FileUpload
                value={file ? [file] : []}
                onValueChange={handleValueChange}
                onAccept={handleAccept}
                onFileReject={onFileReject}
                onFileValidate={validate}
                accept={accept}
                maxFiles={1}
                multiple={false}
                label={label}
                className='min-w-0'
            >
                <FileUploadDropzone className='p-3'>
                    {icon}
                    <div className='flex flex-col gap-0.5 text-center'>
                        <p className='text-xs font-medium text-foreground'>
                            {label}
                        </p>
                        <p className='text-xs text-muted-foreground'>
                            Drag & drop or{' '}
                            <FileUploadTrigger className='cursor-pointer font-medium text-primary underline-offset-4 hover:underline'>
                                browse
                            </FileUploadTrigger>
                        </p>
                    </div>
                </FileUploadDropzone>

                <FileUploadList>
                    {file && (
                        <FileUploadItem value={file}>
                            <FileUploadItemPreview
                                render={
                                    isUploading
                                        ? () => (
                                              <Spinner className='size-5 text-muted-foreground' />
                                          )
                                        : previewUrl
                                          ? () => (
                                                // eslint-disable-next-line @next/next/no-img-element
                                                <img
                                                    src={previewUrl}
                                                    alt='Uploaded image'
                                                    className='size-full object-cover'
                                                />
                                            )
                                          : undefined
                                }
                            />
                            <FileUploadItemMetadata size='sm' />
                            <FileUploadItemDelete asChild>
                                <Button
                                    type='button'
                                    variant='ghost'
                                    size='icon'
                                    className='ml-auto size-7 shrink-0'
                                >
                                    <X className='size-3.5' />
                                </Button>
                            </FileUploadItemDelete>
                        </FileUploadItem>
                    )}
                </FileUploadList>
            </FileUpload>

            {description && <FieldDescription>{description}</FieldDescription>}
            {error && <FieldError errors={[new Error(error)]} />}
        </Field>
    );
};
