import useMangoStore from '../stores/useMangoStore'
import BN from 'bn.js'
import {
  MangoAccount,
  MangoCache,
  MangoGroup,
  nativeI80F48ToUi,
  PerpMarket,
  PerpMarketConfig,
} from '@blockworks-foundation/mango-client'
import useTradeHistory from './useTradeHistory'
import useMangoAccount from './useMangoAccount'
import {
  mangoCacheSelector,
  mangoGroupConfigSelector,
  mangoGroupSelector,
  marketsSelector,
} from '../stores/selectors'

export const collectPerpPosition = (
  mangoAccount: MangoAccount,
  mangoGroup: MangoGroup,
  mangoCache: MangoCache,
  marketConfig: PerpMarketConfig,
  perpMarket: PerpMarket,
  tradeHistory: any
) => {
  if (
    !mangoAccount ||
    !mangoGroup ||
    !mangoCache ||
    !perpMarket ||
    !tradeHistory
  )
    return {}

  const marketIndex = marketConfig.marketIndex
  const perpMarketInfo = mangoGroup.perpMarkets[marketIndex]
  const perpAccount = mangoAccount.perpAccounts[marketIndex]

  let avgEntryPrice = 0,
    breakEvenPrice = 0
  try {
    const perpTradeHistory = tradeHistory.filter(
      (t) => t.marketName === marketConfig.name
    )

    avgEntryPrice = perpAccount
      .getAverageOpenPrice(mangoAccount, perpMarket, perpTradeHistory)
      .toNumber()
    breakEvenPrice = perpAccount
      .getBreakEvenPrice(mangoAccount, perpMarket, perpTradeHistory)
      .toNumber()
  } catch (e) {
    console.error(e)
  }

  const basePosition = perpMarket?.baseLotsToNumber(perpAccount.basePosition)
  const indexPrice = mangoGroup.getPrice(marketIndex, mangoCache).toNumber()
  const notionalSize = Math.abs(basePosition * indexPrice)
  const unrealizedPnl = basePosition * (indexPrice - breakEvenPrice)
  const unsettledPnl = +nativeI80F48ToUi(
    perpAccount.getPnl(
      mangoGroup.perpMarkets[marketIndex],
      mangoCache.perpMarketCache[marketIndex],
      mangoCache.priceCache[marketIndex].price
    ),
    marketConfig.quoteDecimals
  ).toNumber()

  return {
    marketIndex,
    perpMarketInfo,
    marketConfig,
    perpMarket,
    perpAccount,
    basePosition,
    indexPrice,
    avgEntryPrice,
    breakEvenPrice,
    notionalSize,
    unrealizedPnl,
    unsettledPnl,
  }
}

const usePerpPositions = () => {
  const { mangoAccount } = useMangoAccount()
  const groupConfig = useMangoStore(mangoGroupConfigSelector)
  const mangoGroup = useMangoStore(mangoGroupSelector)
  const mangoCache = useMangoStore(mangoCacheSelector)
  const allMarkets = useMangoStore(marketsSelector)
  const tradeHistory = useTradeHistory()

  const perpAccounts = mangoAccount
    ? groupConfig.perpMarkets.map((m) =>
        collectPerpPosition(
          mangoAccount,
          mangoGroup,
          mangoCache,
          m,
          allMarkets[m.publicKey.toBase58()] as PerpMarket,
          tradeHistory
        )
      )
    : []

  const openPositions = perpAccounts.filter(
    ({ perpAccount }) =>
      perpAccount?.basePosition && !perpAccount.basePosition.eq(new BN(0))
  )
  const unsettledPositions = perpAccounts.filter(
    ({ perpAccount, unsettledPnl }) =>
      perpAccount?.basePosition?.eq(new BN(0)) && unsettledPnl != 0
  )

  return { openPositions, unsettledPositions }
}

export default usePerpPositions
