import tw from "twin.macro";
import { Accept, FileError, useDropzone } from "react-dropzone";
import { HTMLAttributes, useMemo } from "react";

/**
 * NejDropzone component for handling file uploads.
 * @param {Object} props - Component props.
 * @param {<T extends File>(files: T[], event: DropEvent) => void} props.onDrop - Callback function triggered when files are dropped.
 * @param {string[]} props.accept - Array of supported file extensions.
 * @param {Array<File>} props.value - The files to be uploaded.
 * @param {boolean} props.single - Whether to allow only one file to be uploaded.
 * @param {<T extends File>(file: T) => FileError | FileError[] | null} props.validator - The validator function to be used.
 * @param {string} props.text - The text to be displayed in the dropzone.
 * @returns {JSX.Element} - NejDropzone component.
 */
export default function NejDropzone({ value, accept, onDrop, validator, single, text, css, children, ...props }: HTMLAttributes<HTMLDivElement> & { value: File | File[], accept?: Accept | string, onDrop: (files: File[]) => void, validator?: (file: File) => FileError | FileError[] | null, single?: boolean, text?: string, css?: any, children?: any }) {

  const { getRootProps, getInputProps, isFocused, isDragAccept, isDragReject } = useDropzone({
    //validator: validator,
    onDropAccepted: onDrop,
    accept: typeof (accept) === "string" ? { [accept]: ["*.*"] } : accept,
    validator: validator,
    maxFiles: single ? 1 : undefined,
  });

  const style = useMemo(
    () => ({
      ...tw`flex flex-col items-center min-h-32 justify-center text-primary p-2 border rounded-xl border-2 border-dashed bg-primary`,
      ...(isFocused && tw`bg-secondary`),
      ...(isDragAccept && tw`border-accent`),
      ...(isDragReject && tw`border-red-600`),
      ...css
    }),
    [isFocused, isDragAccept, isDragReject, css]
  );

  //if file is not array, make it 1 item array
  const array = Array.isArray(value) ? value : [value];
  const fil = value == null ? null : array;

  return (
    <div {...getRootProps({ style })} {...props}>
      <input {...getInputProps()} />
      {children ?? (fil?.length > 0 ? (
        fil.map((file) => (
          <div key={file.name}>
            <p>{file.name}</p>
          </div>
        ))
      ) : (
        <>
          <p>{text ?? "Drag 'n' drop some files here, or click to select files"}</p>
        </>
      ))}
    </div>
  );
}
