import { useEffect, useState } from 'react'
import SwapHistoryTable from '../swap/SwapHistoryTable'
import TradeHistory from '@components/trade/TradeHistory'
import mangoStore from '@store/mangoStore'
import useMangoAccount from 'hooks/useMangoAccount'
import ActivityFeedTable, {
  getCreditAndDebit,
  getFee,
  getValue,
} from './ActivityFeedTable'
import { handleExport } from 'utils/export'
import { LinkButton } from '@components/shared/Button'
import Loading from '@components/shared/Loading'
import { ArrowDownTrayIcon } from '@heroicons/react/20/solid'
import {
  countLeadingZeros,
  floorToDecimal,
  formatCurrencyValue,
  formatNumericValue,
} from 'utils/numbers'
import { formatTokenSymbol } from 'utils/tokens'
import { fetchTradeHistory, parseApiTradeHistory } from 'hooks/useTradeHistory'
import { PublicKey } from '@solana/web3.js'
import { PerpMarket } from '@blockworks-foundation/mango-v4'
import useUnownedAccount from 'hooks/useUnownedAccount'
import SecondaryTabBar from '@components/shared/SecondaryTabBar'
import ActivityFilters from './ActivityFilters'
import { useTranslation } from 'react-i18next'

const TABS = ['activity:activity-feed', 'activity:swaps', 'activity:trades']

const HistoryTabs = () => {
  const { t } = useTranslation(['common', 'account', 'activity', 'trade'])
  const [activeTab, setActiveTab] = useState<string>('activity:activity-feed')
  const actions = mangoStore((s) => s.actions)
  const { mangoAccountAddress } = useMangoAccount()
  const { isUnownedAccount } = useUnownedAccount()
  const [loadExportData, setLoadExportData] = useState(false)

  useEffect(() => {
    if (actions && mangoAccountAddress) {
      actions.fetchActivityFeed(mangoAccountAddress)
    }
  }, [actions, mangoAccountAddress])

  const exportActivityDataToCSV = async () => {
    setLoadExportData(true)
    await actions.fetchActivityFeed(mangoAccountAddress, 0, '', 10000)
    const activityFeed = mangoStore.getState().activityFeed.feed
    const dataToExport = activityFeed.map((row) => {
      const { activity_type, block_datetime } = row
      const { signature } = row.activity_details
      const amounts = getCreditAndDebit(row, mangoAccountAddress)
      const value = getValue(row, mangoAccountAddress)
      const fee = getFee(row, mangoAccountAddress)
      const timestamp = new Date(block_datetime)
      return {
        date: `${timestamp.toLocaleDateString()} ${timestamp.toLocaleTimeString()}`,
        activity: t(`activity:${activity_type}`),
        credit: `${amounts.credit.value} ${amounts.credit.symbol}`,
        debit: `${amounts.debit.value} ${amounts.debit.symbol}`,
        fee: `${fee.value} ${fee.symbol}`,
        value: value.toFixed(3),
        signature,
      }
    })

    const title = `${mangoAccountAddress}-Activity-${new Date().toLocaleDateString()}`

    handleExport(dataToExport, title)
    setLoadExportData(false)
  }

  const exportSwapsDataToCSV = async () => {
    setLoadExportData(true)
    await actions.fetchSwapHistory(mangoAccountAddress, 0, 0, 10000)
    const swapHistory = mangoStore.getState().mangoAccount.swapHistory.data
    const dataToExport = swapHistory.map((row) => {
      const {
        block_datetime,
        signature,
        swap_in_amount,
        swap_in_loan_origination_fee,
        swap_in_symbol,
        swap_out_amount,
        loan,
        loan_origination_fee,
        swap_out_price_usd,
        swap_out_symbol,
      } = row
      const borrowAmount =
        loan > 0 ? `${floorToDecimal(loan, countLeadingZeros(loan) + 2)}` : 0
      const borrowFee =
        swap_in_loan_origination_fee > 0
          ? swap_in_loan_origination_fee.toFixed(4)
          : loan_origination_fee > 0
          ? loan_origination_fee.toFixed(4)
          : 0

      const inSymbol = formatTokenSymbol(swap_in_symbol)
      const outSymbol = formatTokenSymbol(swap_out_symbol)

      const inDecimals = countLeadingZeros(swap_in_amount) + 2
      const outDecimals = countLeadingZeros(swap_out_amount) + 2
      const timestamp = new Date(block_datetime)

      return {
        date: `${timestamp.toLocaleDateString()} ${timestamp.toLocaleTimeString()}`,
        paid: `${formatNumericValue(swap_in_amount, inDecimals)} ${inSymbol}`,
        received: `${formatNumericValue(
          swap_out_amount,
          outDecimals
        )} ${outSymbol}`,
        value: formatCurrencyValue(swap_out_price_usd * swap_out_amount),
        borrow: `${borrowAmount} ${inSymbol}`,
        ['borrow fee']: `${borrowFee} ${inSymbol}`,
        signature,
      }
    })

    const title = `${mangoAccountAddress}-Swaps-${new Date().toLocaleDateString()}`

    handleExport(dataToExport, title)
    setLoadExportData(false)
  }

  const exportTradesDataToCSV = async () => {
    setLoadExportData(true)
    const group = mangoStore.getState().group
    if (!group) return
    const tradeHistory = await fetchTradeHistory(mangoAccountAddress, 0, 10000)
    const dataToExport = tradeHistory.map((row) => {
      const trade = parseApiTradeHistory(mangoAccountAddress, row)
      const timestamp = new Date(trade.block_datetime)
      let market
      if ('market' in trade) {
        market = group.getSerum3MarketByExternalMarket(
          new PublicKey(trade.market)
        )
      } else if ('perp_market' in trade) {
        market = group.getPerpMarketByMarketIndex(trade.market_index)
      }
      const { side, price, size, feeCost, liquidity, signature } = trade
      return {
        date: `${timestamp.toLocaleDateString()} ${timestamp.toLocaleTimeString()}`,
        market: market?.name,
        side:
          market instanceof PerpMarket
            ? side === 'buy'
              ? t('trade:long')
              : t('trade:short')
            : t(side),
        size: size,
        price: price,
        value: (price * size).toFixed(2),
        fee: formatNumericValue(feeCost),
        type: liquidity,
        signature,
      }
    })

    const title = `${mangoAccountAddress}-Trades-${new Date().toLocaleDateString()}`

    handleExport(dataToExport, title)
    setLoadExportData(false)
  }

  const handleExportData = (dataType: string) => {
    if (dataType === 'activity:activity-feed') {
      exportActivityDataToCSV()
    } else if (dataType === 'activity:swaps') {
      exportSwapsDataToCSV()
    } else {
      exportTradesDataToCSV()
    }
  }

  return (
    <>
      <div className="relative">
        <SecondaryTabBar
          activeTab={activeTab}
          setActiveTab={setActiveTab}
          tabs={TABS}
        />
        <div className="flex w-full items-center justify-end border-b border-th-bkg-3 py-3 pr-4 sm:-mt-14 sm:h-14 sm:border-b-0 sm:py-0 md:pr-6">
          {!isUnownedAccount ? (
            <LinkButton
              className="flex items-center font-normal no-underline"
              disabled={loadExportData}
              onClick={() => handleExportData(activeTab)}
            >
              <span className="mr-2">
                {t('account:export', { dataType: t(activeTab) })}
              </span>
              {loadExportData ? (
                <Loading />
              ) : (
                <ArrowDownTrayIcon className="h-5 w-5" />
              )}
            </LinkButton>
          ) : null}
          {activeTab === 'activity:activity-feed' ? <ActivityFilters /> : null}
        </div>
      </div>
      <TabContent activeTab={activeTab} />
    </>
  )
}

const TabContent = ({ activeTab }: { activeTab: string }) => {
  switch (activeTab) {
    case 'activity:activity-feed':
      return <ActivityFeedTable />
    case 'activity:swaps':
      return <SwapHistoryTable />
    case 'activity:trades':
      return <TradeHistory />
    default:
      return <ActivityFeedTable />
  }
}

export default HistoryTabs
