import classNames from 'classnames'
import { useCallback, useMemo } from 'react'

import AssetAmount from 'components/common/assets/AssetAmount'
import ActionButton from 'components/common/Button/ActionButton'
import { ArrowRight } from 'components/common/Icons'
import SummaryLine from 'components/common/SummaryLine'
import Text from 'components/common/Text'
import TradeDirection from 'components/perps/BalancesTable/Columns/TradeDirection'
import { ExpectedPrice } from 'components/perps/Module/ExpectedPrice'
import TradingFee from 'components/perps/Module/TradingFee'
import { BN_ZERO } from 'constants/math'
import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
import useTradingFeeAndPrice from 'hooks/perps/useTradingFeeAndPrice'
import useStore from 'store'
import { BNCoin } from 'types/classes/BNCoin'
import { formatLeverage } from 'utils/formatters'

type Props = {
  leverage: number
  amount: BigNumber
  tradeDirection: TradeDirection
  asset: Asset
  previousAmount: BigNumber
  previousTradeDirection?: 'long' | 'short'
  previousLeverage?: number | null
  hasActivePosition: boolean
  onTxExecuted: () => void
}

export default function PerpsSummary(props: Props) {
  const openPerpPosition = useStore((s) => s.openPerpPosition)
  const modifyPerpPosition = useStore((s) => s.modifyPerpPosition)
  const closePerpPosition = useStore((s) => s.closePerpPosition)
  const currentAccount = useCurrentAccount()

  const newAmount = useMemo(
    () => (props.previousAmount ?? BN_ZERO).plus(props.amount),
    [props.amount, props.previousAmount],
  )
  const { data: tradingFee } = useTradingFeeAndPrice(
    props.asset.denom,
    newAmount,
    props.previousAmount,
  )

  const onConfirm = useCallback(async () => {
    if (!currentAccount) return

    if (!props.previousAmount.isZero() && newAmount.isZero()) {
      await closePerpPosition({
        accountId: currentAccount.id,
        denom: props.asset.denom,
      })
      return props.onTxExecuted()
    }

    if (!props.previousAmount.isZero() && !newAmount.isZero()) {
      await modifyPerpPosition({
        accountId: currentAccount.id,
        coin: BNCoin.fromDenomAndBigNumber(props.asset.denom, newAmount),
        changeDirection: props.previousAmount.isNegative() !== newAmount.isNegative(),
      })
      return props.onTxExecuted()
    }

    await openPerpPosition({
      accountId: currentAccount.id,
      coin: BNCoin.fromDenomAndBigNumber(props.asset.denom, props.amount),
    })
    return props.onTxExecuted()
  }, [closePerpPosition, currentAccount, modifyPerpPosition, newAmount, openPerpPosition, props])

  const disabled = useMemo(() => props.amount.isZero(), [props.amount])

  return (
    <div className='border border-white/10 rounded-sm bg-white/5'>
      <ManageSummary {...props} newAmount={newAmount} />
      <div className='py-4 px-3 flex flex-col gap-1'>
        <Text size='xs' className='font-bold mb-2'>
          Summary
        </Text>
        <SummaryLine label='Expected Price'>
          <ExpectedPrice
            denom={props.asset.denom}
            newAmount={newAmount}
            previousAmount={props.previousAmount}
          />
        </SummaryLine>
        <SummaryLine
          label='Fees'
          tooltip={`${tradingFee ? tradingFee.rate.times(100) + '% ' : ''}Trading Fees`}
        >
          <TradingFee
            denom={props.asset.denom}
            newAmount={newAmount}
            previousAmount={props.previousAmount}
          />
        </SummaryLine>
        <SummaryLine label='Total'>-</SummaryLine>
      </div>
      <ActionButton onClick={onConfirm} disabled={disabled} className='w-full py-2.5'>
        <span className='capitalize mr-1'>{props.tradeDirection}</span>
        {props.asset.symbol}
      </ActionButton>
    </div>
  )
}

function ManageSummary(props: Props & { newAmount: BigNumber }) {
  const showTradeDirection =
    props.previousAmount && props.previousAmount.isNegative() !== props.newAmount.isNegative()
  const showAmount = !props.amount.isZero() && props.previousAmount
  const showLeverage =
    props.previousLeverage &&
    props.leverage &&
    props.previousLeverage.toFixed(2) !== props.leverage.toFixed(2)

  if ((!showTradeDirection && !showLeverage && !showAmount) || !props.hasActivePosition) return null

  return (
    <div className='pt-4 px-3 flex flex-col gap-1'>
      <Text size='xs' className='font-bold mb-2'>
        Your new position
      </Text>

      {props.newAmount.isZero() && (
        <Text size='xs' className='text-white/40 mb-1'>
          Your position will be closed
        </Text>
      )}

      {showTradeDirection && props.previousTradeDirection && !props.newAmount.isZero() && (
        <SummaryLine label='Side' contentClassName='flex gap-1'>
          <TradeDirection tradeDirection={props.previousTradeDirection} />
          <ArrowRight width={16} />
          <TradeDirection tradeDirection={props.tradeDirection} />
        </SummaryLine>
      )}

      {showAmount && props.newAmount && props.previousAmount && !props.newAmount.isZero() && (
        <SummaryLine label='Size' contentClassName='flex gap-1'>
          <AssetAmount asset={props.asset} amount={props.previousAmount.abs().toNumber()} />
          <ArrowRight
            width={16}
            className={classNames(
              props.previousAmount.abs().isGreaterThan(props.newAmount)
                ? 'text-error'
                : 'text-success',
            )}
          />
          <AssetAmount
            asset={props.asset}
            amount={props.previousAmount.plus(props.amount).abs().toNumber()}
          />
        </SummaryLine>
      )}

      {showLeverage && props.previousLeverage && (
        <SummaryLine label='Leverage' contentClassName='flex gap-1'>
          <span>{formatLeverage(props.previousLeverage)}</span>
          <ArrowRight
            width={16}
            className={classNames(
              props.leverage > props.previousLeverage ? 'text-error' : 'text-success',
            )}
          />
          <span>{formatLeverage(props.leverage)}</span>
        </SummaryLine>
      )}
    </div>
  )
}
