import { useEffect, useMemo, useState } from 'react'
import dayjs from 'dayjs'
import useMangoStore from '../../stores/useMangoStore'
import { Table, Td, Th, TrBody, TrHead } from '../TableElements'
import { isEmpty } from 'lodash'
import { useTranslation } from 'next-i18next'
import Select from '../Select'
import Pagination from '../Pagination'
import usePagination from '../../hooks/usePagination'
import { roundToDecimal } from '../../utils'
import Chart from '../Chart'
import Switch from '../Switch'
import useLocalStorageState from '../../hooks/useLocalStorageState'
import { handleDustTicks } from './AccountInterest'

const utc = require('dayjs/plugin/utc')
dayjs.extend(utc)
import { exportDataToCSV } from '../../utils/export'
import Button from '../Button'
import { SaveIcon } from '@heroicons/react/outline'

const QUOTE_DECIMALS = 6

const AccountFunding = () => {
  const { t } = useTranslation('common')
  const mangoAccount = useMangoStore((s) => s.selectedMangoAccount.current)
  const [fundingStats, setFundingStats] = useState<any>([])
  const [hourlyFunding, setHourlyFunding] = useState<any>([])
  const [selectedAsset, setSelectedAsset] = useState<string>('BTC')
  const [loadHourlyStats, setLoadHourlyStats] = useState(false)
  const [loadTotalStats, setLoadTotalStats] = useState(false)
  const {
    paginatedData,
    setData,
    totalPages,
    nextPage,
    previousPage,
    page,
    firstPage,
    lastPage,
  } = usePagination(hourlyFunding[selectedAsset])
  const [hideFundingDust, setHideFundingDust] = useLocalStorageState(
    'hideFundingDust',
    false
  )
  const [chartData, setChartData] = useState([])
  const [showHours, setShowHours] = useState(false)

  const mangoAccountPk = useMemo(() => {
    return mangoAccount.publicKey.toString()
  }, [mangoAccount])

  const exportFundingDataToCSV = () => {
    const assets = Object.keys(hourlyFunding)
    let dataToExport = []

    for (const asset of assets) {
      dataToExport = [
        ...dataToExport,
        ...hourlyFunding[asset].map((funding) => {
          const timestamp = new Date(funding.time)
          return {
            timestamp: `${timestamp.toLocaleDateString()} ${timestamp.toLocaleTimeString()}`,
            asset: asset,
            amount: funding.total_funding,
          }
        }),
      ]
    }

    const title = `${
      mangoAccount.name || mangoAccount.publicKey
    }-Funding-${new Date().toLocaleDateString()}`
    const columns = ['Timestamp', 'Asset', 'Amount']

    exportDataToCSV(dataToExport, title, columns, t)
  }

  useEffect(() => {
    if (!isEmpty(hourlyFunding)) {
      setData(hourlyFunding[selectedAsset])
    }
  }, [selectedAsset, hourlyFunding])

  useEffect(() => {
    const hideDust = []
    const fetchFundingStats = async () => {
      setLoadTotalStats(true)
      const response = await fetch(
        `https://mango-transaction-log.herokuapp.com/v3/stats/total-funding?mango-account=${mangoAccountPk}`
      )
      const parsedResponse = await response.json()

      if (hideFundingDust) {
        Object.entries(parsedResponse).forEach((r: any) => {
          const funding = r[1].total_funding
          if (Math.abs(funding) > 1) {
            hideDust.push(r)
          }
        })
        setLoadTotalStats(false)
        setFundingStats(hideDust)
      } else {
        setLoadTotalStats(false)
        setFundingStats(Object.entries(parsedResponse))
      }
    }

    const fetchHourlyFundingStats = async () => {
      setLoadHourlyStats(true)
      const response = await fetch(
        `https://mango-transaction-log.herokuapp.com/v3/stats/hourly-funding?mango-account=${mangoAccountPk}`
      )
      const parsedResponse = await response.json()

      let assets
      if (hideFundingDust) {
        const assetsToShow = hideDust.map((a) => a[0])
        assets = Object.keys(parsedResponse).filter((a) =>
          assetsToShow.includes(a)
        )
        setSelectedAsset(assetsToShow[0])
      } else {
        assets = Object.keys(parsedResponse)
      }

      const stats = {}
      for (const asset of assets) {
        const x: any = Object.entries(parsedResponse[asset])

        stats[asset] = x
          .map(([key, value]) => {
            const funding = roundToDecimal(
              value.total_funding,
              QUOTE_DECIMALS + 1
            )
            if (funding !== 0) {
              return { ...value, time: key }
            } else {
              return null
            }
          })
          .filter((x) => x)
          .reverse()
      }

      setLoadHourlyStats(false)
      setHourlyFunding(stats)
    }

    const getStats = async () => {
      await fetchFundingStats()
      fetchHourlyFundingStats()
    }
    getStats()
  }, [mangoAccountPk, hideFundingDust])

  useEffect(() => {
    if (hourlyFunding[selectedAsset]) {
      const start = new Date(
        // @ts-ignore
        dayjs().utc().hour(0).minute(0).subtract(29, 'day')
      ).getTime()

      const filtered = hourlyFunding[selectedAsset].filter(
        (d) => new Date(d.time).getTime() > start
      )

      const dailyFunding = []

      filtered.forEach((d) => {
        const found = dailyFunding.find(
          (x) =>
            dayjs(x.time).format('DD-MMM') === dayjs(d.time).format('DD-MMM')
        )
        if (found) {
          const newFunding = d.total_funding
          found.funding = found.funding + newFunding
        } else {
          dailyFunding.push({
            time: d.time,
            funding: d.total_funding,
          })
        }
      })
      if (dailyFunding.length <= 1) {
        const chartFunding = []
        hourlyFunding[selectedAsset].forEach((a) => {
          chartFunding.push({
            funding: a.total_funding,
            time: a.time,
          })
        })
        setShowHours(true)
        setChartData(chartFunding.reverse())
      } else {
        setShowHours(false)
        setChartData(dailyFunding.reverse())
      }
    }
  }, [hourlyFunding, selectedAsset])

  useEffect(() => {
    if (!selectedAsset && Object.keys(hourlyFunding).length > 0) {
      setSelectedAsset(Object.keys(hourlyFunding)[0])
    }
  }, [hourlyFunding])

  return (
    <>
      <div className="flex items-center justify-between pb-4">
        <div className="text-th-fgd-1 text-lg">{t('total-funding')}</div>
        <div className="flex items-center">
          <Button
            className={`float-right text-xs h-8 pt-0 pb-0 pl-3 pr-3`}
            onClick={exportFundingDataToCSV}
          >
            <div className={`flex items-center whitespace-nowrap`}>
              <SaveIcon className={`h-4 w-4 mr-1.5`} />
              {t('export-data')}
            </div>
          </Button>
          <Switch
            checked={hideFundingDust}
            className="ml-2 text-xs"
            onChange={() => setHideFundingDust(!hideFundingDust)}
          >
            {t('hide-dust')}
          </Switch>
        </div>
      </div>
      {mangoAccount ? (
        <div>
          {loadTotalStats ? (
            <div className="space-y-2">
              <div className="animate-pulse bg-th-bkg-3 h-12 rounded-md w-full" />
              <div className="animate-pulse bg-th-bkg-3 h-12 rounded-md w-full" />
              <div className="animate-pulse bg-th-bkg-3 h-12 rounded-md w-full" />
            </div>
          ) : (
            <Table>
              <thead>
                <TrHead>
                  <Th>{t('token')}</Th>
                  <Th>{t('total-funding')} (USDC)</Th>
                </TrHead>
              </thead>
              <tbody>
                {fundingStats.length === 0 ? (
                  <TrBody index={0}>
                    <td colSpan={4}>
                      <div className="flex">
                        <div className="mx-auto py-4 text-th-fgd-3">
                          {t('no-funding')}
                        </div>
                      </div>
                    </td>
                  </TrBody>
                ) : (
                  fundingStats.map(([symbol, stats], index) => {
                    return (
                      <TrBody index={index} key={symbol}>
                        <Td className="w-1/2">
                          <div className="flex items-center">
                            <img
                              alt=""
                              width="20"
                              height="20"
                              src={`/assets/icons/${symbol.toLowerCase()}.svg`}
                              className={`mr-2.5`}
                            />
                            {symbol}-PERP
                          </div>
                        </Td>
                        <Td className="w-1/2">
                          <div
                            className={`${
                              stats.total_funding > 0
                                ? 'text-th-green'
                                : stats.total_funding < 0
                                ? 'text-th-red'
                                : 'text-th-fgd-3'
                            }`}
                          >
                            {stats.total_funding
                              ? `${stats.total_funding?.toFixed(6)}`
                              : '-'}
                          </div>
                        </Td>
                      </TrBody>
                    )
                  })
                )}
              </tbody>
            </Table>
          )}

          <>
            {!isEmpty(hourlyFunding) && !loadHourlyStats ? (
              <>
                <div className="flex items-center justify-between pb-4 pt-6 w-full">
                  <div className="text-th-fgd-1 text-lg">{t('history')}</div>
                  <Select
                    value={selectedAsset}
                    onChange={(a) => setSelectedAsset(a)}
                    className="w-24 sm:hidden"
                  >
                    <div className="space-y-2">
                      {Object.keys(hourlyFunding).map((token: string) => (
                        <Select.Option
                          key={token}
                          value={token}
                          className={`bg-th-bkg-1 relative rounded-md w-full px-3 py-3 cursor-pointer default-transition flex hover:bg-th-bkg-3 focus:outline-none`}
                        >
                          <div className="flex items-center justify-between w-full">
                            {token}
                          </div>
                        </Select.Option>
                      ))}
                    </div>
                  </Select>
                  <div className="hidden sm:flex pb-4 sm:pb-0">
                    {Object.keys(hourlyFunding).map((token: string) => (
                      <div
                        className={`px-2 py-1 ml-2 rounded-md cursor-pointer default-transition bg-th-bkg-3
                          ${
                            selectedAsset === token
                              ? `ring-1 ring-inset ring-th-primary text-th-primary`
                              : `text-th-fgd-1 opacity-50 hover:opacity-100`
                          }
                        `}
                        onClick={() => setSelectedAsset(token)}
                        key={token}
                      >
                        {token}-PERP
                      </div>
                    ))}
                  </div>
                </div>
                {selectedAsset && chartData.length > 0 ? (
                  <div className="flex flex-col sm:flex-row space-x-0 sm:space-x-4 w-full">
                    <div
                      className="border border-th-bkg-4 relative mb-6 p-4 rounded-md w-full"
                      style={{ height: '330px' }}
                    >
                      <Chart
                        daysRange={showHours ? 1 : 30}
                        hideRangeFilters
                        title={t('funding-chart-title', {
                          symbol: selectedAsset,
                        })}
                        xAxis="time"
                        yAxis="funding"
                        data={chartData}
                        labelFormat={(x) =>
                          x &&
                          `${x?.toLocaleString(undefined, {
                            maximumFractionDigits: 6,
                          })} USDC`
                        }
                        tickFormat={handleDustTicks}
                        type="bar"
                        yAxisWidth={70}
                      />
                    </div>
                  </div>
                ) : null}
                <div>
                  <div>
                    {paginatedData.length ? (
                      <Table>
                        <thead>
                          <TrHead>
                            <Th>{t('time')}</Th>
                            <Th>{t('funding')} (USDC)</Th>
                          </TrHead>
                        </thead>
                        <tbody>
                          {paginatedData.map((stat, index) => {
                            // @ts-ignore
                            const utc = dayjs.utc(stat.time).format()

                            return (
                              <TrBody index={index} key={stat.time}>
                                <Td className="w-1/2">
                                  {dayjs(utc).format('DD/MM/YY, h:mma')}
                                </Td>
                                <Td className="w-1/2">
                                  {stat.total_funding.toFixed(
                                    QUOTE_DECIMALS + 1
                                  )}
                                </Td>
                              </TrBody>
                            )
                          })}
                        </tbody>
                      </Table>
                    ) : (
                      <div className="flex justify-center w-full bg-th-bkg-3 py-4 text-th-fgd-3">
                        {t('no-funding')}
                      </div>
                    )}
                  </div>
                  <Pagination
                    page={page}
                    totalPages={totalPages}
                    nextPage={nextPage}
                    lastPage={lastPage}
                    firstPage={firstPage}
                    previousPage={previousPage}
                  />
                </div>
              </>
            ) : loadHourlyStats ? (
              <div className="pt-8 space-y-2">
                <div className="animate-pulse bg-th-bkg-3 h-12 rounded-md w-full" />
                <div className="animate-pulse bg-th-bkg-3 h-12 rounded-md w-full" />
                <div className="animate-pulse bg-th-bkg-3 h-12 rounded-md w-full" />
              </div>
            ) : null}
          </>
        </div>
      ) : (
        <div>{t('connect-wallet')}</div>
      )}
    </>
  )
}

export default AccountFunding
