import { FC, Fragment, useState, useEffect } from 'react';
import {
  Modal,
  Box,
  Text,
  Heading,
  Flex,
  Link,
  Hr,
  Paragraph,
  TooltipIcon,
  ButtonLarge,
} from '@polymathnetwork/polymesh-ui';
import { BigNumber } from '@polymathnetwork/polymesh-sdk';
import { useTranslation } from 'react-i18next';
import {
  ConfirmationStatus,
  DetailItem,
  Section,
  TranslationNS,
} from './definition';
import { calcTxCost } from '../utils/calcTxCost';
import * as formatters from '../utils/formatters';
import * as heap from '../analytics/heap';

export const TxConfirmModal: FC<{
  store: any;
  appStateActions: any;
  transactionActions: any;
  tokenSymbol: string;
}> = ({ store, appStateActions, transactionActions, tokenSymbol }) => {
  const { t } = useTranslation(TranslationNS.ConfirmModal);
  const [protocolFees, setProtocolFees] = useState<BigNumber | undefined>(
    undefined,
  );
  const [gasFees, setGasFees] = useState<BigNumber | undefined>(undefined);
  const { dispatch, getState } = store;
  const {
    transaction: { signingPackage },
    polymesh: { selectedAccount, accountBalances, inFlight },
  } = getState();
  const {
    confirmationStatus,
    confirmationData,
    queue,
    apiQueue,
    id: signingPackageId,
  } = signingPackage || {};
  const isApi = !!apiQueue;
  const balances = accountBalances[selectedAccount];
  const enoughBalance = balances?.available.gte(
    protocolFees?.plus(gasFees || 0) || 0,
  );
  const hasFees = new BigNumber(protocolFees || 0).toNumber() > 0;

  useEffect(() => {
    const getFees = async () => {
      if (!queue) {
        setProtocolFees(undefined);
        setGasFees(undefined);
      } else if (isApi) {
        const cost = await calcTxCost(queue, selectedAccount || '');
        setGasFees(cost);
        setProtocolFees(confirmationData?.apiProtocolFee);
      } else {
        const fees = await queue.getMinFees();
        setProtocolFees(fees.protocol);
        setGasFees(fees.gas);
      }
    };
    getFees();
  }, [queue]); // eslint-disable-line

  const setConfirmationStatus = (status: ConfirmationStatus) => {
    dispatch(transactionActions.setConfirmationStatus(status));
  };

  const renderItem = (
    item: DetailItem,
    itemIndex: number,
    isLastItem: boolean,
  ) => {
    let formattedValue = item.value;
    if (item.value instanceof Date) {
      formattedValue = formatters.toDateString(item.value);
    } else if (item.value && item.translate) {
      formattedValue = t(formattedValue as string);
    } else if (item.value && item.value.toString().length > 25) {
      formattedValue = formatters.shortenString(item.value?.toString(), {
        size: 25,
      });
    }

    return (
      <Fragment key={itemIndex}>
        <Flex
          justifyContent="space-between"
          {...(isLastItem ? {} : { mb: 'm' })}
        >
          <Text variant="b1m" color="gray.2">
            {t(`${item.label}`)}
          </Text>
          {item.link ? (
            <Link id={`confirm_modal_item_link_${itemIndex}`} href={item.link}>
              {formattedValue}
            </Link>
          ) : (
            <Text variant="b1m" color="highlightText">
              {formattedValue || '[None]'}
            </Text>
          )}
        </Flex>
        {((!isLastItem && item.hr !== false) || item.hr) && (
          <Hr color="gray.4" />
        )}
      </Fragment>
    );
  };

  const renderSectionItems = (items: DetailItem[]) => {
    return items.map((item, index) =>
      renderItem(item, index, index + 1 === items.length),
    );
  };

  const renderSections = (sections: Section[]) =>
    sections.map((section, index) => (
      <Fragment key={`section${index.toString()}`}>
        {section.label && (
          <Box>
            <Heading variant="h5" mb="m" mt="4">
              {t(`${section.label}`)}
            </Heading>
          </Box>
        )}
        {renderSectionItems(section.items)}
      </Fragment>
    ));

  const onCancel = () => {
    setConfirmationStatus(ConfirmationStatus.None);
    if (inFlight) dispatch(appStateActions.setAsync(false));
  };

  return (
    <Modal
      isCloseable={false}
      isOpen={confirmationStatus === ConfirmationStatus.Pending}
      maxWidthContainer={750}
    >
      <Modal.Body width={656}>
        <Box>
          <Heading variant="h5">
            {t(`${confirmationData?.title}`, confirmationData?.titleArgs)}
          </Heading>
        </Box>
        {confirmationData?.message && (
          <Box>
            <Paragraph mt={20}>
              {t(`${confirmationData.message}`, confirmationData?.messageArgs)}
            </Paragraph>
          </Box>
        )}
        {confirmationData?.body && <Box mt="m">{confirmationData.body}</Box>}
        {confirmationData?.sections && (
          <Box mt="l">{renderSections(confirmationData.sections)}</Box>
        )}
        {confirmationData?.footer && (
          <Box mt="m">{confirmationData.footer}</Box>
        )}
      </Modal.Body>
      <Modal.Footer>
        <Flex justifyContent={hasFees ? 'space-between' : 'flex-end'}>
          {hasFees && (
            <Flex flexDirection="column" alignItems="flex-start">
              <Flex
                flex={1}
                flexDirection="row"
                justifyContent="space-between"
                mt="1"
              >
                <Box>
                  <Text variant="b3m" color="gray.2">
                    Total cost
                  </Text>
                </Box>
                <Box mb={1} ml="s">
                  <TooltipIcon
                    content="This will be withdrawn from your wallet balance."
                    iconButtonProps={{
                      buttonProps: {
                        onMouseEnter: heap.hover({
                          id: 'confirm_modal_cost_tooltip',
                        }),
                      },
                    }}
                  />
                </Box>
              </Flex>
              <Box>
                <Text variant="b2m" color="gray.1">
                  {formatters.formatAmount(protocolFees || new BigNumber(0))}
                </Text>
                <Text variant="b2m" color="gray.2">
                  {` ${tokenSymbol}`}
                </Text>
              </Box>
            </Flex>
          )}
          {!enoughBalance && (
            <Text
              color="alert"
              fontSize="0"
              fontWeight="bold"
              width="15%"
              mr="m"
            >
              Insufficent funds available
            </Text>
          )}
          <Box>
            <ButtonLarge
              id={`${signingPackageId}_confirm_modal_cancel_button`}
              variant="secondary"
              onClick={onCancel}
            >
              {t('General:cancel')}
            </ButtonLarge>
            <ButtonLarge
              id={`${signingPackageId}_confirm_modal_confirm_button`}
              disabled={!enoughBalance}
              onClick={() => setConfirmationStatus(ConfirmationStatus.Done)}
            >
              {confirmationData?.submitButtonTitle || t('General:confirm')}
            </ButtonLarge>
          </Box>
        </Flex>
      </Modal.Footer>
    </Modal>
  );
};
