import React, { useEffect } from 'react';
import { IconButton, useToaster, Placeholder, Stack, Button} from 'rsuite';
import { Panel, Table } from 'rsuite';
import DashboardDrawer from '@/components/dashboard/drawer';
import CheckRoundIcon from '@rsuite/icons/CheckRound';
import DoingRoundIcon from '@rsuite/icons/DoingRound';
import WarningRoundIcon from '@rsuite/icons/WarningRound';
import RemindRoundIcon from '@rsuite/icons/RemindRound';
import UnvisibleIcon from '@rsuite/icons/Unvisible';
import VisibleIcon from '@rsuite/icons/Visible';
import PlusIcon from '@rsuite/icons/Plus';
import ConfirmModal from '@/components/modal/confirmModal';
import { DocumentInfo, UserInfo } from '@/lib/utils/types';
import { capitalizeFirstLetter, sizeToString } from '@/lib/utils/string';
import { DrawerRowData } from '@/lib/utils/types';
import UploadModal from '@/components/dashboard/modal/uploadModal';
import { useModal } from '@/lib/utils/useModal';
import { userAuthAtom, userAtom } from '@/lib/context/user';
import { useAtom } from 'jotai';
import { readUserInfo, updateUserInfo } from '@/lib/firebase/firestore/user';
import { getPlanDetails, PlanDetail } from '@/lib/utils/getPlanDetails';
import { ToastError, ToastSuccess } from '@/components/toasts';
import { toastDefaultProps } from '@/lib/utils/toast';
import { withUser } from '@/components/withUser';
import { createApiKey } from '@/lib/utils/keyGenerator';

type fixedType = boolean | "left" | "right" | undefined


const ApiInfo: React.FC = () => {
  const [open, setOpen] = React.useState(false);
  const [display, setDisplay] = React.useState(false);
  const [loading, setLoading] = React.useState(false);
  const [_userInfo, setUserInfo] = useAtom(userAtom);
  const toaster = useToaster();

  // FIXME: This is a hack to make the type checker happy
  const userInfo = _userInfo as UserInfo;


  const fakeApi = '' + userInfo.apiKey.replace(/./g, '•')


  async function handlerApiRenew() {
    setLoading(true);
    const newKey = createApiKey();

    const res = await updateUserInfo(userInfo.uid, { apiKey: newKey })
    if (res.error) {
      toaster.push(<ToastError msg={res.error} />, toastDefaultProps);
    }

    setUserInfo({ ...userInfo, apiKey: newKey })
    setLoading(false);
  }

  async function onConfirm() {
    setTimeout(() => {
      handlerApiRenew();
      setOpen(false);
    }, 500);
  }


  return (
    <Panel
      bordered
      style={{
        padding: 16,
        backgroundColor: '#fff',
        boxShadow: '3px 3px 0px 0px rgba(0, 0, 0, 0.12)',
      }}
    >
      <Stack spacing={8} direction='column' alignItems='stretch'>
        <Stack spacing={8}>
          <strong>Your API Key is:</strong>
          <p>{display ? userInfo.apiKey : fakeApi}</p>
          <IconButton
            circle
            icon={display ? <VisibleIcon /> : <UnvisibleIcon />}
            onClick={() => setDisplay(!display)}
             />
        </Stack>

        <Button onClick={() => setOpen(true)} appearance={'primary'} loading={loading}>
          Renew
        </Button>
      </Stack>

      <ConfirmModal
        open={open}
        onConfirm={onConfirm}
        onCancel={() => setOpen(false)}
      />
    </Panel>
  )
}


interface QuotaInfoProps {
  userDocuments: DocumentInfo[];
  planDetail: PlanDetail;
}

const QuotaInfo: React.FC<QuotaInfoProps> = ({ userDocuments, planDetail }) => {
  const [userInfo, setUserInfo] = useAtom(userAtom);

  return (
    <Panel
      bordered
      style={{
        padding: 16,
        backgroundColor: '#fff',
        boxShadow: '3px 3px 0px 0px rgba(0, 0, 0, 0.12)',
      }}
    >
      <Stack spacing={8}>
        <p>You have used {userDocuments.length} / {planDetail.nbDocuments} documents from your Quota</p>
        <a>Upgrade to increase your quota</a>
      </Stack>
    </Panel>
  )
}


interface CellProps {
  rowData?: any;
  dataKey: string;

  [x: string]: any;
}

const StatusField: React.FC<CellProps> = ({ rowData, dataKey, ...props }) => {
  const setIcon = (status: string) => {
    switch (rowData[dataKey]) {
      case 'error': return <WarningRoundIcon style={{ color: '#F44336' }} />;
      case 'pending': return <DoingRoundIcon pulse style={{ color: '#2196F3' }} />;
      case 'warning': return <RemindRoundIcon style={{ color: '#FFB300' }} />;
      default: return <CheckRoundIcon style={{ color: '#4CAF50' }} />;
    }
  }

  return (
    <Table.Cell {...props}>
      <Stack spacing={8}>
        <Stack.Item>
          {setIcon(rowData[dataKey])}
        </Stack.Item>

        <Stack.Item>
          {rowData[dataKey] !== undefined ? capitalizeFirstLetter(rowData[dataKey]) : null}
        </Stack.Item>
      </Stack>
    </Table.Cell>
  );
};

const SizeField: React.FC<CellProps> = ({ rowData, dataKey, ...props }) => {
  return (
    <Table.Cell {...props}>
      {sizeToString(rowData[dataKey])}
    </Table.Cell>
  );
};


const DashboardTable: React.FC = () => {
  // Modal
  const { isOpen: modalOpen, onOpen: onModalOpen, onClose: onModalClose } = useModal();

  // Data
  const [user, setUser] = useAtom(userAuthAtom);
  const [userInfo, setUserInfo] = useAtom(userAtom);
  const [planDetail, setPlanDetail] = React.useState<PlanDetail>();
  const [loading, setLoading] = React.useState(false);
  const [compact, setCompact] = React.useState(false);
  const [extRowData, setExtRowData] = React.useState({});

  // Drawer
  const [open, setOpen] = React.useState(false);

  const toaster = useToaster();

  const columnInfo = [
    { key: 'id', header: 'ID', fixed: 'left' as fixedType, width: 80 },
    { key: 'name', header: 'Name', width: 100, flexGrow: 1 },
    { key: 'source', header: 'Source', width: 100, flexGrow: 1 },
    { key: 'status', header: 'Status', width: 100 },
    { key: 'size', header: 'Size', width: 100 },
    { key: 'lastUpdated', header: 'Last Updated', width: 100, flexGrow: 1 },
    { key: 'nbColumns', header: 'Nb Columns', width: 80 },
    { key: 'nbRows', header: 'Nb Rows', width: 80 },
  ]

  React.useEffect(() => {
    async function fetchUserInfo() {
      if (user) {
        const res = await readUserInfo(user.uid);

        if (res.error) {
          toaster.push(<ToastError msg={res.error} />, toastDefaultProps)
          return;
        }

        if (res.data) {
          setPlanDetail(getPlanDetails(res.data.plan));
          setUserInfo(res.data);
        }
      }
    }

    fetchUserInfo();

  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [setUserInfo, user]);

  function chooseCell(key: string) {
    switch (key) {
      case 'status': return (<StatusField dataKey={key} />);
      case 'size': return (<SizeField dataKey={key} />);
      default: return (<Table.Cell dataKey={key} />);
    }
  }

  return (
    <>
      <Stack spacing={24} direction='column' alignItems='stretch'>
        <h1>Dashboard</h1>

        {userInfo && planDetail
          ? <ApiInfo />
          : <Placeholder.Paragraph style={{ marginTop: 30 }} />
        }

        {userInfo && planDetail
          ? <QuotaInfo userDocuments={userInfo.documents} planDetail={planDetail}/>
          : <Placeholder.Paragraph style={{ marginTop: 30 }} />
        }

        <Panel
          bordered
          style={{
            padding: 8,
            borderRadius: 6,
            backgroundColor: '#fff',
            boxShadow: '3px 3px 0px 0px rgba(0, 0, 0, 0.12)',
          }}
        >
          <Table
            loading={loading}
            // height={300}
            hover
            showHeader
            virtualized
            fillHeight={false}
            autoHeight={true}
            bordered={false}
            data={userInfo ? userInfo.documents : []}
            cellBordered={false}
            headerHeight={compact ? 30 : 40}
            rowHeight={compact ? 30 : 46}
            onRowClick={(rowData: object) => {
              setExtRowData(rowData);
              setOpen(true);
            }}
          >
            {
              columnInfo.map(column => {
                const { key, header, ...rest } = column;
                return (
                  <Table.Column key={key} {...rest}>
                    <Table.HeaderCell>{header}</Table.HeaderCell>
                    {chooseCell(key)}
                  </Table.Column>
                );
              })
            }
          </Table>

          <IconButton
            appearance="primary"
            icon={<PlusIcon />}
            onClick={() => { onModalOpen() }}
            block
          >Import new document</IconButton>

        </Panel>
      </Stack>

      {withUser(user, (user) =>
        <DashboardDrawer
          open={open}
          setOpen={setOpen}
          rowData={extRowData as DrawerRowData}
          userId={user.uid}
        />
      )}


      <UploadModal
        isOpen={modalOpen}
        onOpen={onModalOpen}
        onClose={onModalClose}
      />

    </>
  );
};

export default DashboardTable;