import { useState, useEffect, FC } from "react";
import { Stack, Progress } from "rsuite";
import { startUploadFile } from "@/lib/firebase/cloudstore/uploadFile";
import { UploadModalStepProps, ParsedDataGetterProps, ImportDataGetterProps, DocumentInfoGetterProps, DocumentInfoSetterProps} from "../uploadModal";
import { createDocumentKey, getCurrentTimeStamp } from "@/lib/utils/keyGenerator";
import { addNewDocument } from "@/lib/firebase/firestore/user";
import { DocumentInfo, UserInfo } from "@/lib/utils/types";
import { useAtom } from "jotai";
import { userAuthAtom, userAtom } from "@/lib/context/user";
import { gzip, Gzip, gzipSync } from "zlib";


enum SubStep {
  Upload = "Uploading document...",
  Alive = "Checking that API is live...",
  OK = "Everything should be OK.",
}

const subSteps: { [subStep: number]: SubStep } = {
  0: SubStep.Upload,
  1: SubStep.Alive,
  2: SubStep.OK,
}
const subStepCount = Object.keys(subSteps).length

const UploadModalSetupStep: FC<UploadModalStepProps
  & ImportDataGetterProps
  & ParsedDataGetterProps
  & DocumentInfoSetterProps
  > = ({
  setValidStep,
  importData,
  parsedData,
  setDocumentInfo,
}) => {
  const [user] = useAtom(userAuthAtom);
  const [userInfo, setUserInfo] = useAtom(userAtom);
  const [percent, setPercent] = useState(0);
  const [error, setError] = useState<string | null>(null);
  const [documentID] = useState(createDocumentKey());

  var [subStep, setSubStep] = useState(0)
  const currentSubStep = subSteps[subStep];

  useEffect(() => {
    if(importData.type == null || userInfo == null || user == null) return;
    
    switch (currentSubStep) {

      case SubStep.Upload:
        const headers = Object.keys(parsedData.data[0]);
        const firstRow = parsedData.data[0] as any;
        const firstCell = firstRow[headers[0]];
        const parsedDataText = JSON.stringify(parsedData.data);

        // TODO: move inside the startUploadFile function
        const compressedData = gzipSync(parsedDataText);

        const blob = new Blob([compressedData], { type: 'application/json' })
        
        const name = `${documentID}.json`
        const documentInfo: DocumentInfo = {
          id: documentID,
          name: name,
          source: importData.type == 'url' ? importData.url : 'imported',
          size: Number((compressedData.length / 1000).toFixed(2)), // KB
          lastUpdated: new Date().toDateString(),
          nbColumns: parsedData.columns,
          nbRows: parsedData.rows,
          headers: headers,
          firstCell: firstCell
        }
        setDocumentInfo(documentInfo)

        startUploadFile(blob, name, {
          onProgress: (p) => setPercent(Math.round(p / 2)),
          onError: (err) => setError(err),
          onComplete: () => {
            addNewDocument(documentInfo, user.uid)
              .then(() => {
                setSubStep(subStep + 1)
              })
              .catch((err) => {
                setError(err)
              })
          }
        })

        // To avoid re-fetch data from firestore and update the document table,
        // we update the user info in the context
        setUserInfo({
          ...userInfo,
          documents: [
            ...userInfo.documents,
            documentInfo
          ]
        } as UserInfo)

        break;

      case SubStep.Alive:
        // TODO check if api is alive
        setPercent(75);

        const timeout = setTimeout(() => {
          setSubStep(++subStep)
          setPercent(100);
        }, 1000)

        return () => { clearTimeout(timeout); }

      case SubStep.OK:
        setValidStep(true)

      default:
        break;
    }
  }, [documentID, currentSubStep, subStep, importData, parsedData, setValidStep, setPercent, setError, setSubStep])


  /** RENDER */
  const style = {
    width: 120,
    display: 'inline-block',
    marginRight: 10
  };

  return <Stack
    direction="column"
    alignItems="center"
    justifyContent="center"
    spacing={16}
  >
    <Stack.Item>
      <Progress.Circle style={style} percent={percent} status={error != null ? 'fail' : currentSubStep == SubStep.OK ? 'success' : 'active'} />
    </Stack.Item>
    <Stack.Item>
      {currentSubStep}
    </Stack.Item>

  </Stack>
}

export default UploadModalSetupStep