import type { LiFiStep, StepExtended } from '@lifi/sdk';
import { ArrowForward, ExpandLess, ExpandMore } from '@mui/icons-material';
import type { StepIconProps } from '@mui/material';
import {
  Badge,
  Box,
  Collapse,
  Step as MuiStep,
  Stepper,
  Typography,
} from '@mui/material';
import type { MouseEventHandler } from 'react';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { formatUnits } from 'viem';
import { useAvailableChains } from '../../hooks/useAvailableChains.js';
import { LiFiToolLogo } from '../../icons/lifi.js';
import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js';
import { HiddenUI } from '../../types/widget.js';
import { formatTokenAmount } from '../../utils/format.js';
import { CardIconButton } from '../Card/CardIconButton.js';
import { SmallAvatar } from '../SmallAvatar.js';
import {
  StepAvatar,
  StepConnector,
  StepContent,
  StepLabel,
  StepLabelTypography,
} from './StepActions.style.js';
import { StepFees } from './StepFees.js';
import type {
  IncludedStepsProps,
  StepActionsProps,
  StepDetailsLabelProps,
} from './types.js';
import { ChainId } from '../../types/base.js';
import { safeBigInt } from '../../utils/utils.js';

export const StepActions: React.FC<StepActionsProps> = ({
  step,
  dense,
  ...other
}) => {
  const { t } = useTranslation();
  const {
    subvariant,
    // brandingLogo
  } = useWidgetConfig();
  const [cardExpanded, setCardExpanded] = useState(false);

  const handleExpand: MouseEventHandler<HTMLButtonElement> = (e) => {
    e.stopPropagation();
    Promise.resolve().then(() => {
      setCardExpanded((expanded) => !expanded);
    });
  };

  // FIXME: step transaction request overrides step tool details, but not included step tool details
  const toolDetails =
    subvariant === 'custom'
      ? step?.includedSteps?.find(
          (step) => step.tool === 'custom' && step.toolDetails.key !== 'custom',
        )?.toolDetails || step.toolDetails
      : step.toolDetails;

  return (
    <Box {...other}>
      <Box display="flex" alignItems="center">
        <Badge
        // overlap="circular"
        // anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
        // badgeContent={
        //   <SmallAvatar src={brandingLogo ? brandingLogo : LiFiToolLogo} />
        // }
        >
          <StepAvatar
            variant="circular"
            src={toolDetails?.logoURI ?? LiFiToolLogo}
            alt={toolDetails?.name}
          >
            {toolDetails?.name?.[0]}
          </StepAvatar>
        </Badge>
        <Box flex={1}>
          <Typography fontSize={18} fontWeight={600} lineHeight={1.3334} ml={2}>
            {toolDetails?.name?.includes('LI.FI')
              ? toolDetails.name
              : t(`main.stepDetails`, {
                  tool: toolDetails?.name,
                })}
          </Typography>
          <StepFees ml={2} step={step} />
        </Box>
        {dense ? (
          <CardIconButton onClick={handleExpand} size="small">
            {cardExpanded ? (
              <ExpandLess fontSize="inherit" />
            ) : (
              <ExpandMore fontSize="inherit" />
            )}
          </CardIconButton>
        ) : null}
      </Box>
      {dense ? (
        <Collapse timeout={225} in={cardExpanded} mountOnEnter unmountOnExit>
          <IncludedSteps step={step} />
        </Collapse>
      ) : (
        <IncludedSteps step={step} />
      )}
    </Box>
  );
};

export const IncludedSteps: React.FC<IncludedStepsProps> = ({ step }) => {
  const { t } = useTranslation();

  const {
    subvariant,
    subvariantOptions,
    feeConfig,
    hiddenUI,
    // commissionBps,
    commissionBpsSDK,
  } = useWidgetConfig();

  let includedSteps = step.includedSteps;
  if (hiddenUI?.includes(HiddenUI.IntegratorStepDetails)) {
    const feeCollectionStep = includedSteps.find(
      (step) => step.tool === 'feeCollection',
    );
    if (feeCollectionStep) {
      includedSteps = structuredClone(
        includedSteps.filter((step) => step.tool !== 'feeCollection'),
      );
      includedSteps[0].estimate.fromAmount =
        feeCollectionStep.estimate.fromAmount;
    }
  }

  // eslint-disable-next-line react/no-unstable-nested-components
  const StepIconComponent = ({ icon }: StepIconProps) => {
    const includedStep = includedSteps?.[Number(icon) - 1];
    const feeCollectionStep =
      includedStep?.type === 'protocol' &&
      includedStep?.tool === 'feeCollection';
    const toolName =
      feeCollectionStep && feeConfig?.name
        ? feeConfig?.name
        : includedStep?.toolDetails?.name;
    const toolLogoURI =
      feeCollectionStep && feeConfig?.logoURI
        ? feeConfig?.logoURI
        : includedStep?.toolDetails.logoURI;
    return toolLogoURI ? (
      <SmallAvatar
        src={toolLogoURI}
        alt={toolName}
        sx={{ width: 20, height: 20 }}
      >
        {toolName?.[0]}
      </SmallAvatar>
    ) : null;
  };

  return (
    <Box mt={1}>
      <Stepper
        orientation="vertical"
        connector={<StepConnector />}
        activeStep={-1}
      >
        {(includedSteps || [])?.map((step, i, includedSteps) => (
          <MuiStep key={step.id} expanded>
            <StepLabel StepIconComponent={StepIconComponent}>
              {step.type === 'custom' && subvariant === 'custom' ? (
                <CustomStepDetailsLabel
                  step={step}
                  subvariant={subvariant}
                  subvariantOptions={subvariantOptions}
                />
              ) : step.type === 'cross' ? (
                <BridgeStepDetailsLabel step={step} />
              ) : step.type === 'protocol' ? (
                <ProtocolStepDetailsLabel step={step} feeConfig={feeConfig} />
              ) : (
                <SwapStepDetailsLabel step={step} />
              )}
            </StepLabel>
            <StepContent last={i === includedSteps.length - 1}>
              <StepDetailsContent step={step} />
            </StepContent>
          </MuiStep>
        ))}
      </Stepper>

      {commissionBpsSDK && commissionBpsSDK[ChainId.MOVE] ? (
        <Box display="flex" justifyContent="space-between" mt={1}>
          <Typography variant="body2" fontWeight="500">
            Swap Fee
          </Typography>
          <Typography variant="body2">
            {t('format.percent', {
              value:
                commissionBpsSDK &&
                commissionBpsSDK[ChainId.MOVE] &&
                commissionBpsSDK[ChainId.MOVE] / 10000,
            })}
          </Typography>
        </Box>
      ) : null}
    </Box>
  );
};

export const StepDetailsContent: React.FC<{
  step: StepExtended;
}> = ({ step }) => {
  const { t } = useTranslation();

  const sameTokenProtocolStep =
    step.action.fromToken?.chainId === step.action.toToken?.chainId &&
    step.action.fromToken?.address === step.action.toToken?.address;

  let fromAmount: string | undefined;
  if (sameTokenProtocolStep) {
    const estimatedFromAmount =
      safeBigInt(step?.estimate?.fromAmount) -
      safeBigInt(step?.estimate?.toAmount);

    fromAmount =
      estimatedFromAmount > 0n
        ? formatUnits(
            estimatedFromAmount,
            step?.action?.fromToken?.decimals || 0,
          )
        : formatUnits(
            safeBigInt(step?.estimate?.fromAmount),
            step?.action?.fromToken?.decimals || 0,
          );
  } else {
    fromAmount = formatTokenAmount(
      safeBigInt(step?.estimate?.fromAmount),
      step?.action?.fromToken?.decimals || 0,
    );
  }

  const showToAmount =
    step.type !== 'custom' && step.tool !== 'custom' && !sameTokenProtocolStep;

  return (
    <Typography
      fontSize={12}
      lineHeight={1}
      fontWeight="500"
      color="text.secondary"
      alignItems="center"
      display="flex"
    >
      {!showToAmount ? (
        <>
          {formatUnits(
            safeBigInt(step?.estimate?.fromAmount),
            step?.action?.fromToken?.decimals || 0,
          )}{' '}
          {step?.action?.fromToken?.symbol}
          {' - '}
        </>
      ) : null}
      {t('format.number', {
        value: fromAmount,
      })}{' '}
      {step?.action?.fromToken?.symbol}
      {showToAmount ? (
        <>
          <ArrowForward sx={{ fontSize: 18, paddingX: 0.5, height: 12 }} />
          {t('format.number', {
            value: formatTokenAmount(
              safeBigInt(step?.execution?.toAmount ?? step?.estimate?.toAmount),
              step.execution?.toToken?.decimals ??
                (step.action.toToken?.decimals || 0),
            ),
          })}{' '}
          {step.execution?.toToken?.symbol ?? step.action.toToken?.symbol}
        </>
      ) : (
        ` (${t('format.currency', {
          value:
            parseFloat(fromAmount || '0') *
            parseFloat(step?.action?.fromToken?.priceUSD || '0'),
        })})`
      )}
    </Typography>
  );
};

export const CustomStepDetailsLabel: React.FC<StepDetailsLabelProps> = ({
  step,
  subvariant,
  subvariantOptions,
}) => {
  const { t } = useTranslation();

  if (!subvariant) {
    return null;
  }

  // FIXME: step transaction request overrides step tool details, but not included step tool details
  const toolDetails =
    subvariant === 'custom' &&
    (step as unknown as LiFiStep).includedSteps?.length > 0
      ? (step as unknown as LiFiStep).includedSteps.find(
          (step) => step.tool === 'custom' && step.toolDetails.key !== 'custom',
        )?.toolDetails || step.toolDetails
      : step.toolDetails;

  const stepDetailsKey =
    (subvariant === 'custom' && subvariantOptions?.custom) || 'checkout';

  return (
    <StepLabelTypography>
      {t(`main.${stepDetailsKey}StepDetails`, {
        tool: toolDetails.name,
      })}
    </StepLabelTypography>
  );
};

export const BridgeStepDetailsLabel: React.FC<
  Omit<StepDetailsLabelProps, 'variant'>
> = ({ step }) => {
  const { t } = useTranslation();
  const { getChainById } = useAvailableChains();
  return (
    <StepLabelTypography>
      {t('main.bridgeStepDetails', {
        from: getChainById(step.action.fromChainId)?.name,
        to: getChainById(step.action.toChainId)?.name,
        tool: step.toolDetails.name,
      })}
    </StepLabelTypography>
  );
};

export const SwapStepDetailsLabel: React.FC<
  Omit<StepDetailsLabelProps, 'variant'>
> = ({ step }) => {
  const { t } = useTranslation();
  const { getChainById } = useAvailableChains();
  return (
    <StepLabelTypography>
      {t('main.swapStepDetails', {
        chain: getChainById(step.action.fromChainId)?.name,
        tool: step.toolDetails.name,
      })}
    </StepLabelTypography>
  );
};

export const ProtocolStepDetailsLabel: React.FC<
  Omit<StepDetailsLabelProps, 'variant'>
> = ({ step, feeConfig }) => {
  const { t } = useTranslation();
  return (
    <StepLabelTypography>
      {step.toolDetails.key === 'feeCollection'
        ? feeConfig?.name
          ? t('main.fees.integrator', { tool: feeConfig.name })
          : t('main.fees.defaultIntegrator')
        : step.toolDetails.key === 'lifuelProtocol'
          ? t('main.refuelStepDetails', {
              tool: step.toolDetails.name,
            })
          : step.toolDetails.name}
    </StepLabelTypography>
  );
};
