import type { FC } from 'react';
import React from 'react';
import cx from 'classnames';
import { useDropzone } from 'react-dropzone';
import { InfoMessage } from '../infoMessage';
import { LoadingSpinner } from '../loadingSpinner';
import { isLegacyProps } from './types';
import { UploadAreaLegacy } from './uploadAreaLegacy';
import { UploadAreaStatus } from './uploadAreaStatus';
import type { UploadAreaProps, UploadAreaLegacyProps } from './types';
const CLASS_NAME = 'UploadArea';

/**
 * UploadArea is a UI component that allows users to upload files to an app, either by clicking a browsing button or by drag & dropping a file into a dedicated upload area.
 *
 * @type organism
 * @status live
 * @tags form-elements
 */
export const UploadArea: FC<UploadAreaProps | UploadAreaLegacyProps> = (props) => {
    const {
        children,
        className,
        style,
        testId = CLASS_NAME,
        onUpload,
        inputId,
        accept = '*',
        maxFiles = 0,
        multipleFileSelection = true,
        validator,
        onDropRejected,
        disabled = false,
    } = props;

    const dropzoneState = useDropzone({
        noClick: true,
        onDrop: onUpload,
        accept,
        maxFiles,
        multiple: multipleFileSelection,
        validator,
        onDropRejected,
        disabled,
    });
    const { getRootProps, isDragActive, getInputProps, open } = dropzoneState;

    if (isLegacyProps(props))
        return (
            <UploadAreaLegacy
                className={className}
                style={style}
                testId={testId}
                inputId={inputId}
                multipleFileSelection={multipleFileSelection}
                dropzoneState={dropzoneState}
            >
                {children}
            </UploadAreaLegacy>
        );

    const { variant, info, uploadStatus, errorMessage } = props;
    const isSpinner = info.illustration === 'spinner';
    const illustration = isSpinner ? undefined : info.illustration ?? 'uploadArea';

    const openFileUploadDialog = (event: React.MouseEvent) => {
        event.preventDefault();
        open();
    };

    return (
        <div
            className={cx(CLASS_NAME, className, `${CLASS_NAME}-${variant}`)}
            style={style}
            data-testid={testId}
        >
            <div
                {...getRootProps({
                    className: cx(`${CLASS_NAME}-dropzone`, {
                        [`${CLASS_NAME}-dropzone-active`]: isDragActive,
                        [`${CLASS_NAME}-dropzone-disabled`]: disabled,
                    }),
                    role: 'none',
                    onClick: openFileUploadDialog,
                })}
            >
                <input
                    {...getInputProps({
                        className: `${CLASS_NAME}-input`,
                        id: inputId,
                    })}
                    {...(multipleFileSelection
                        ? { webkitdirectory: '', mozdirectory: '', directory: '' }
                        : {})}
                />
                <InfoMessage
                    variant={variant}
                    illustration={illustration}
                    Icon={
                        isSpinner ? (
                            <LoadingSpinner
                                show
                                size={variant === 'small' ? 48 : 80}
                                percentage={info.percentage}
                            />
                        ) : undefined
                    }
                    title={info.title}
                    description={info.description}
                    width="auto"
                />
                {children}
            </div>
            {errorMessage && (
                <div
                    className={`${CLASS_NAME}-error-message`}
                    data-testid={`${testId}-error-message`}
                    role="alert"
                >
                    {errorMessage}
                </div>
            )}
            {uploadStatus && <UploadAreaStatus {...uploadStatus} />}
        </div>
    );
};
