import { Dispatch, SetStateAction, useEffect, useRef, useState, ChangeEventHandler, FC } from "react";
import { Stack, InputGroup, Input, Divider, IconButton } from "rsuite";
import { UploadModalStepProps, ImportDataSetterProps, UploadModalImportData } from "../uploadModal";
import { useToaster } from 'rsuite';
import { ToastError, ToastSuccess } from '@/components/toasts';
import { toastDefaultProps } from '@/lib/utils/toast';

import FileIcon from '@rsuite/icons/Page';
import CloseIcon from '@rsuite/icons/Close';
import { getValidExtensions } from "@/lib/firebase/cloudstore/uploadFile";


const validExtension = getValidExtensions();

const ERR_MSG_INVALID_FILE = 'Please upload a valid file\nValid extensions: ' + validExtension.join(', ')

function useValidateStep(url: string, file: File | null, setValidStep: Dispatch<SetStateAction<boolean>>) {
  const isFileValid = file != null;

  // TODO improve with URL regex
  const isUrlValid = url.startsWith('http://') || url.startsWith('https://')

  const isValid = isUrlValid || isFileValid;

  useEffect(() => {
    setValidStep(isValid)

    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [url, file, setValidStep])

  return { isValid, isUrlValid, isFileValid };
}

function useUpdateImportDataOnceValid(
  isValid: boolean,
  data: UploadModalImportData,
  setImportData: Dispatch<SetStateAction<UploadModalImportData>>
) {
  useEffect(() => {
    if (isValid && data.type != null) {
      setImportData(data)
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [isValid, setImportData])
}

function buildImportData(
  isFileValid: boolean,
  isUrlValid: boolean,
  file: File | null,
  url: string
): UploadModalImportData {
  if (isFileValid && file != null) {
    return { type: 'file', file }
  } else if (isUrlValid) {
    return { type: 'url', url }
  } else {
    return { type: null }
  }
}

const UploadModalImportStep: FC<UploadModalStepProps & ImportDataSetterProps> = ({
  setValidStep,
  setImportData
}) => {
  const toaster = useToaster();

  const uploadInputRef = useRef<HTMLInputElement>(null)
  const [uploadInputKey, setUploadInputKey] = useState(0);

  var [url, setUrl] = useState("")
  const [file, setFile] = useState<File | null>(null);

  // Validate local
  const { isValid, isFileValid, isUrlValid } = useValidateStep(url, file, setValidStep);

  // Update upper import data state state 
  const importData = buildImportData(isFileValid, isUrlValid, file, url)
  useUpdateImportDataOnceValid(isValid, importData, setImportData);

  function handleUploadButtonClick() {
    uploadInputRef.current?.click()
  }

  // function
  const handleFileChange: ChangeEventHandler<HTMLInputElement> = (event) => {
    const fileList = event.target.files;

    if (fileList) {
      const file = fileList[0];

      // Check extension
      const extension = file.name.split('.').pop();
      if (extension && validExtension.includes(extension)) {
        setFile(fileList[0])
        return;
      }

      toaster.push(<ToastError msg={ERR_MSG_INVALID_FILE} />, toastDefaultProps);
    }
  }

  function resetFileInput() {
    setFile(null);
    // Force re render of file input 
    setUploadInputKey(uploadInputKey + 1)
  }


  /** RENDER */

  return <Stack
    direction="column"
    alignItems="flex-start"
    justifyContent="center"
    spacing={16}
  >

    <Stack.Item >
      <label>Paste URL here:</label>
      <InputGroup>
        <Input type="text" disabled={file != null} placeholder="https://..." value={url} onChange={(value) => { setUrl(value) }} />
        {url != ""
          ? <InputGroup.Button onClick={() => setUrl('')}>
            <CloseIcon />
          </InputGroup.Button>
          : null}

      </InputGroup>
    </Stack.Item>
    <Divider>OR</Divider>
    <Stack.Item >
      <Stack spacing={16}>
        <Stack.Item >
          <IconButton onClick={handleUploadButtonClick} disabled={url != ""} icon={<FileIcon />}>Upload a file</IconButton>
          <input type="file" key={uploadInputKey} ref={uploadInputRef} style={{ display: 'none' }}
            onChange={handleFileChange} />
        </Stack.Item>
        <Stack.Item >
          {file != null
            ? <>{file.name} ({(file.size / 1000).toFixed(2)} KB) <CloseIcon onClick={resetFileInput} /></>
            : null}
        </Stack.Item>
      </Stack>
    </Stack.Item>

  </Stack>
}

export default UploadModalImportStep