import { useState, useCallback } from 'react';
import { Link, useNavigate, useParams } from 'react-router-dom';
import { useDropzone } from 'react-dropzone';
import { useQuery } from '@apollo/client';
import { WORKSPACE } from 'components/workspace/schema/queries';
import { handleGraphQLError } from 'lib/appsync/utils';
import { QUOTA_EXCEEDED_EXCEPTION } from 'lib/appsync/errorTypes';

import { useModal } from 'components/layers';

import { Button, Spinner, Text } from 'components/common';
import { Header } from 'components/Header';
import { ErrorBoundary } from 'components/ErrorBoundary';
import { ReactComponent as FileIconSVG } from 'assets/icons/file.svg';
import { UpgradeSubscriptionModal } from 'components/billing/modals';
import { FileItem } from 'components/import/FileItem';
import { UploadFooter } from 'components/import/UploadFooter';
import {
  useComplexFileUpload,
  STATUS,
} from 'components/import/useComplexFileUpload';

const COLOR_GRAY = '#8291a433';
const COLOR_GREEN = '#00c800aa';
const COLOR_RED = '#e91e63aa';
const COLOR_BLUE = '#2f80edaa';

function switchText(
  state: string,
  message: Record<string, string> & { default: string }
) {
  return message[state] ? message[state] : message.default;
}

const ACCEPT = '.csv';

export const UploadDataPage = () => {
  const { workspaceId } = useParams();
  const [file, setFile] = useState<File | null>(null);

  const { data } = useQuery(WORKSPACE, {
    variables: { workspaceId },
    fetchPolicy: 'cache-first',
  });

  const navigate = useNavigate();

  const upgradeSubscriptionModal = useModal(UpgradeSubscriptionModal);

  const handleCollectionStatus = (collection: {
    id: string;
    status: string;
  }) => {
    const { id, status } = collection;
    if (status === STATUS.LABELING) {
      navigate(id);
    }
  };

  const { submit, upload, status, error } = useComplexFileUpload(
    workspaceId!,
    handleCollectionStatus
  );

  const exception = handleGraphQLError(error, QUOTA_EXCEEDED_EXCEPTION);
  if (exception) {
    upgradeSubscriptionModal.show({ message: exception.message });
  }

  const handleFile = useCallback((file) => {
    if (file instanceof File) {
      setFile(file);
    }
  }, []);

  const removeFile = () => {
    setFile(null);
  };

  const onFileInput: React.ChangeEventHandler<HTMLInputElement> = (ev) => {
    const files = ev.currentTarget.files;
    if (files) {
      handleFile(files[0]);
    }
  };

  const onDrop = useCallback(
    (acceptedFiles) => {
      const file = acceptedFiles[0];
      handleFile(file);
    },
    [handleFile]
  );

  const {
    getRootProps,
    // getInputProps,
    isDragActive,
  } = useDropzone({
    onDrop,
    accept: ACCEPT,
    noKeyboard: true,
  });

  return (
    <ErrorBoundary>
      <div className="h100 flex flexColumn">
        <Header
          left={
            <Link to=".." className="c-black link">
              {data?.workspace?.name}
            </Link>
          }
          title="Import CSV file"
        />
        <div
          className="relative flexGrow flex flexColumn alignCenter justifyCenter"
          {...getRootProps()}
        >
          <div className="flex flexColumn alignCenter justifyCenter w50 padding4 tac">
            <div style={{ width: 64 }}>
              <FileIconSVG
                fill={
                  isDragActive
                    ? COLOR_BLUE
                    : file
                    ? status === STATUS.FAILED
                      ? COLOR_RED
                      : COLOR_GREEN
                    : COLOR_GRAY
                }
              />
            </div>
            <div className="flex alignCenter justifyCenter w100 h25 marginY10">
              {file ? (
                <div className="w100">
                  <FileItem
                    file={file}
                    removeFile={removeFile} // TODO disable when "uploaded"
                    progress={status === STATUS.UPLOADING ? upload.progress : 0}
                    error={
                      status === STATUS.FAILED
                        ? 'Something went wrong'
                        : undefined
                    }
                  />
                </div>
              ) : (
                <div>
                  <Text weight="bold">Drag and drop file</Text>
                  <Text>or click to select one</Text>
                </div>
              )}
            </div>
            {file ? (
              <Button
                size="l"
                onClick={() => submit(file)}
                disabled={
                  [STATUS.UPLOADING, STATUS.UPLOADED, STATUS.LABELING].indexOf(
                    status
                  ) !== -1
                }
              >
                {switchText(status, {
                  [STATUS.UPLOADING]: 'Uploading...',
                  [STATUS.UPLOADED]: 'Redirecting...',
                  [STATUS.LABELING]: 'Redirecting...',
                  [STATUS.FAILED]: 'Try again',
                  default: 'Upload',
                })}
              </Button>
            ) : (
              <Button size="l" as="label">
                <input
                  type="file"
                  name="file"
                  accept={ACCEPT}
                  onChange={onFileInput}
                  hidden
                />
                Select file
              </Button>
            )}
          </div>
          <Spinner show={status === STATUS.LOADING} />
        </div>
        <UploadFooter />
      </div>
    </ErrorBoundary>
  );
};
