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

import AccountBalancesTable from 'components/Account/AccountBalancesTable'
import AccountComposition from 'components/Account/AccountComposition'
import AccountDetailsLeverage from 'components/Account/AccountDetails/AccountDetailsLeverage'
import Skeleton from 'components/Account/AccountDetails/Skeleton'
import EscButton from 'components/Button/EscButton'
import { glowElement } from 'components/Button/utils'
import Card from 'components/Card'
import DisplayCurrency from 'components/DisplayCurrency'
import { FormattedNumber } from 'components/FormattedNumber'
import { HealthGauge } from 'components/HealthGauge'
import { ThreeDots } from 'components/Icons'
import Text from 'components/Text'
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
import { REDUCE_MOTION_KEY } from 'constants/localStore'
import { ORACLE_DENOM } from 'constants/oracle'
import useAccountId from 'hooks/useAccountId'
import useAccounts from 'hooks/useAccounts'
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
import useCurrentAccount from 'hooks/useCurrentAccount'
import useHealthComputer from 'hooks/useHealthComputer'
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
import useLocalStorage from 'hooks/useLocalStorage'
import usePrices from 'hooks/usePrices'
import useStore from 'store'
import { BNCoin } from 'types/classes/BNCoin'
import {
  calculateAccountApr,
  calculateAccountBalanceValue,
  calculateAccountLeverage,
} from 'utils/accounts'

export default function AccountDetailsController() {
  const address = useStore((s) => s.address)
  const { isLoading } = useAccounts(address)
  const accountId = useAccountId()
  const account = useCurrentAccount()
  const focusComponent = useStore((s) => s.focusComponent)

  if (!address || focusComponent) return null

  if ((isLoading && accountId && !focusComponent) || !account) return <Skeleton />

  return <AccountDetails account={account} />
}

interface Props {
  account: Account
}

function AccountDetails(props: Props) {
  const { account } = props
  const [reduceMotion] = useLocalStorage<boolean>(REDUCE_MOTION_KEY, DEFAULT_SETTINGS.reduceMotion)
  const updatedAccount = useStore((s) => s.updatedAccount)
  const accountDetailsExpanded = useStore((s) => s.accountDetailsExpanded)
  const { health } = useHealthComputer(account)
  const { health: updatedHealth } = useHealthComputer(updatedAccount || account)
  const { data: prices } = usePrices()
  const accountBalanceValue = useMemo(
    () => calculateAccountBalanceValue(updatedAccount ?? account, prices),
    [updatedAccount, account, prices],
  )
  const coin = BNCoin.fromDenomAndBigNumber(ORACLE_DENOM, accountBalanceValue)
  const leverage = useMemo(() => calculateAccountLeverage(account, prices), [account, prices])
  const updatedLeverage = useMemo(() => {
    if (!updatedAccount) return null
    const updatedLeverage = calculateAccountLeverage(updatedAccount, prices)

    if (updatedLeverage.eq(leverage)) return null
    return updatedLeverage
  }, [updatedAccount, prices, leverage])

  const { availableAssets: borrowAvailableAssets, accountBorrowedAssets } =
    useBorrowMarketAssetsTableData()
  const { availableAssets: lendingAvailableAssets, accountLentAssets } =
    useLendingMarketAssetsTableData()
  const borrowAssetsData = useMemo(
    () => [...borrowAvailableAssets, ...accountBorrowedAssets],
    [borrowAvailableAssets, accountBorrowedAssets],
  )
  const lendingAssetsData = useMemo(
    () => [...lendingAvailableAssets, ...accountLentAssets],
    [lendingAvailableAssets, accountLentAssets],
  )
  const apr = useMemo(
    () =>
      calculateAccountApr(updatedAccount ?? account, borrowAssetsData, lendingAssetsData, prices),
    [account, borrowAssetsData, lendingAssetsData, prices, updatedAccount],
  )

  function AccountDetailsHeader() {
    const onClose = useCallback(() => useStore.setState({ accountDetailsExpanded: false }), [])

    return (
      <div className='flex items-center justify-between w-full p-4 bg-white/10 '>
        <Text size='lg' className='flex items-center flex-grow font-semibold'>
          {`Credit Account ${account.id}`}
        </Text>
        <EscButton onClick={onClose} hideText className='w-6 h-6' />
      </div>
    )
  }

  return (
    <div
      data-testid='account-details'
      className={classNames(
        accountDetailsExpanded ? 'right-6.5' : '-right-80',
        'w-100 flex items-start gap-4 absolute top-6',
        !reduceMotion && 'transition-all duration-300',
      )}
    >
      <div
        className={classNames(
          'flex flex-wrap min-w-16 w-16 group relative',
          'border rounded-base border-white/20',
          'bg-white/5 backdrop-blur-sticky',
          !reduceMotion && 'transition-colors duration-300',
          'hover:bg-white/10 hover:cursor-pointer ',
        )}
        onClick={() => useStore.setState({ accountDetailsExpanded: !accountDetailsExpanded })}
      >
        <div className='flex flex-wrap justify-center w-full py-4'>
          <HealthGauge health={health} updatedHealth={updatedHealth} />
          <Text size='2xs' className='mb-0.5 mt-1 w-full text-center text-white/50'>
            Health
          </Text>
        </div>
        <div className='w-full py-4 border-t border-white/20'>
          <Text size='2xs' className='mb-0.5 w-full text-center text-white/50 whitespace-nowrap'>
            Net worth
          </Text>
          <DisplayCurrency coin={coin} className='w-full text-center truncate text-2xs ' />
        </div>
        <div className='w-full py-4 border-t border-white/20'>
          <Text size='2xs' className='mb-0.5 w-full text-center text-white/50'>
            Leverage
          </Text>
          <AccountDetailsLeverage
            leverage={leverage.toNumber() || 1}
            updatedLeverage={updatedLeverage?.toNumber() || null}
          />
        </div>
        <div className='w-full py-4 border-t border-white/20'>
          <Text size='2xs' className='mb-0.5 w-full text-center text-white/50'>
            APR
          </Text>
          <FormattedNumber
            className={'w-full text-center text-2xs'}
            amount={apr.toNumber()}
            options={{ maxDecimals: 2, minDecimals: 2, suffix: '%' }}
            animate
          />
        </div>
        <div
          className={classNames(
            'flex justify-center items-center w-full h-6 opacity-50',
            !reduceMotion && 'transition-[opacity] duration-300',
            'absolute -bottom-6',
            'group-hover:opacity-100',
          )}
        >
          {!accountDetailsExpanded && <ThreeDots className='h-1' />}
        </div>

        {glowElement(!reduceMotion)}
      </div>
      <div className='flex w-90 backdrop-blur-sticky'>
        <Card className='w-full bg-white/5' title={<AccountDetailsHeader />}>
          <AccountComposition account={account} />
          <Text className='w-full px-4 py-2 text-white bg-white/10'>Balances</Text>
          <AccountBalancesTable
            account={account}
            borrowingData={borrowAssetsData}
            lendingData={lendingAssetsData}
          />
        </Card>
      </div>
    </div>
  )
}
