import { useState, useEffect, useMemo } from 'react'
import { useTheme } from 'next-themes'
import cloneDeep from 'lodash/cloneDeep'
import dayjs from 'dayjs'
import {
  AreaChart,
  Area,
  XAxis,
  YAxis,
  Tooltip as ChartTooltip,
} from 'recharts'
import { InformationCircleIcon, ScaleIcon } from '@heroicons/react/solid'
import useDimensions from 'react-cool-dimensions'
import { useTranslation } from 'next-i18next'
import { ZERO_BN } from '@blockworks-foundation/mango-client'
import ButtonGroup from '../ButtonGroup'
import { formatUsdValue } from '../../utils'
import { numberCompacter } from '../SwapTokenInfo'
import Checkbox from '../Checkbox'
import Tooltip from '../Tooltip'
import useMangoStore, { PerpPosition } from 'stores/useMangoStore'
import LongShortChart from './LongShortChart'
import HealthHeart from 'components/HealthHeart'

type AccountOverviewStats = {
  hourlyPerformanceStats: any[]
  performanceRange: '24hr' | '7d' | '30d' | '3m'
}

const defaultData = [
  { account_equity: 0, pnl: 0, time: '2022-01-01T00:00:00.000Z' },
  { account_equity: 0, pnl: 0, time: '2023-01-01T00:00:00.000Z' },
]

const performanceRangePresets = [
  { label: '24h', value: 1 },
  { label: '7d', value: 7 },
  { label: '30d', value: 30 },
  { label: '3m', value: 90 },
]
const performanceRangePresetLabels = performanceRangePresets.map((x) => x.label)

const AccountOverviewStats = ({ hourlyPerformanceStats, accountValue }) => {
  const { theme } = useTheme()
  const { t } = useTranslation('common')
  const { observe, width, height } = useDimensions()
  const [chartToShow, setChartToShow] = useState<string>('Value')
  const [chartData, setChartData] = useState<any[]>([])
  const [mouseData, setMouseData] = useState<string | null>(null)
  const [performanceRange, setPerformanceRange] = useState('30d')
  const [showSpotPnl, setShowSpotPnl] = useState(true)
  const [showPerpPnl, setShowPerpPnl] = useState(true)
  const mangoAccount = useMangoStore((s) => s.selectedMangoAccount.current)
  const mangoGroup = useMangoStore((s) => s.selectedMangoGroup.current)
  const mangoCache = useMangoStore((s) => s.selectedMangoGroup.cache)
  const spotBalances = useMangoStore((s) => s.selectedMangoAccount.spotBalances)
  const perpPositions = useMangoStore(
    (s) => s.selectedMangoAccount.perpPositions
  )

  const maintHealthRatio = useMemo(() => {
    return mangoAccount && mangoGroup && mangoCache
      ? mangoAccount.getHealthRatio(mangoGroup, mangoCache, 'Maint')
      : 100
  }, [mangoAccount, mangoGroup, mangoCache])

  const { longData, shortData, longExposure, shortExposure } = useMemo(() => {
    const longData: any = []
    const shortData: any = []

    if (!spotBalances || !perpPositions) {
      longData.push({ symbol: 'spacer', value: 1 })
      shortData.push({ symbol: 'spacer', value: 1 })
      // return {}
    }

    const DUST_THRESHOLD = 0.05
    const netUnsettledPositionsValue = perpPositions.reduce(
      (a, c) => a + (c?.unsettledPnl ?? 0),
      0
    )

    for (const { net, symbol, value } of spotBalances) {
      let amount = Number(net)
      let totValue = Number(value)
      if (symbol === 'USDC') {
        amount += netUnsettledPositionsValue
        totValue += netUnsettledPositionsValue
      }
      if (totValue > DUST_THRESHOLD) {
        longData.push({
          asset: symbol,
          amount: amount,
          symbol: symbol,
          value: totValue,
        })
      }
      if (-totValue > DUST_THRESHOLD) {
        shortData.push({
          asset: symbol,
          amount: Math.abs(amount),
          symbol: symbol,
          value: Math.abs(totValue),
        })
      }
    }
    for (const {
      marketConfig,
      basePosition,
      notionalSize,
      perpAccount,
    } of perpPositions.filter((p) => !!p) as PerpPosition[]) {
      if (notionalSize < DUST_THRESHOLD) continue

      if (perpAccount.basePosition.gt(ZERO_BN)) {
        longData.push({
          asset: marketConfig.name,
          amount: basePosition,
          symbol: marketConfig.baseSymbol,
          value: notionalSize,
        })
      } else {
        shortData.push({
          asset: marketConfig.name,
          amount: Math.abs(basePosition),
          symbol: marketConfig.baseSymbol,
          value: notionalSize,
        })
      }
    }
    const longExposure = longData.reduce((a, c) => a + c.value, 0)
    const shortExposure = shortData.reduce((a, c) => a + c.value, 0)
    if (shortExposure === 0) {
      shortData.push({ symbol: 'spacer', value: 1 })
    }
    if (longExposure === 0) {
      longData.push({ symbol: 'spacer', value: 1 })
    }
    const dif = longExposure - shortExposure
    if (dif > 0) {
      shortData.push({ symbol: 'spacer', value: dif })
    }

    return { longData, shortData, longExposure, shortExposure }
  }, [spotBalances, perpPositions])

  useEffect(() => {
    if (hourlyPerformanceStats.length > 0) {
      if (performanceRange === '3m') {
        setChartData(hourlyPerformanceStats.slice().reverse())
      }
      if (!chartData?.length) return
      if (performanceRange === '30d') {
        const start = new Date(
          // @ts-ignore
          dayjs().utc().hour(0).minute(0).subtract(29, 'day')
        ).getTime()
        const chartData = cloneDeep(hourlyPerformanceStats).filter(
          (d) => new Date(d.time).getTime() > start
        )

        const pnlStart = chartData[chartData.length - 1]?.pnl
        const perpPnlStart = chartData[chartData.length - 1].perp_pnl
        for (let i = 0; i < chartData.length; i++) {
          if (i === chartData.length - 1) {
            chartData[i].pnl = 0
            chartData[i].perp_pnl = 0
          } else {
            chartData[i].pnl = chartData[i].pnl - pnlStart
            chartData[i].perp_pnl = chartData[i].perp_pnl - perpPnlStart
          }
        }
        setChartData(chartData.reverse())
      }
      if (performanceRange === '7d') {
        const start = new Date(
          // @ts-ignore
          dayjs().utc().hour(0).minute(0).subtract(7, 'day')
        ).getTime()
        const chartData = cloneDeep(hourlyPerformanceStats).filter(
          (d) => new Date(d.time).getTime() > start
        )
        const pnlStart = chartData[chartData.length - 1].pnl
        const perpPnlStart = chartData[chartData.length - 1].perp_pnl
        for (let i = 0; i < chartData.length; i++) {
          if (i === chartData.length - 1) {
            chartData[i].pnl = 0
            chartData[i].perp_pnl = 0
          } else {
            chartData[i].pnl = chartData[i].pnl - pnlStart
            chartData[i].perp_pnl = chartData[i].perp_pnl - perpPnlStart
          }
        }
        setChartData(chartData.reverse())
      }
      if (performanceRange === '24h') {
        const start = new Date(
          // @ts-ignore
          dayjs().utc().hour(0).minute(0).subtract(1, 'day')
        ).getTime()
        const chartData = cloneDeep(hourlyPerformanceStats).filter(
          (d) => new Date(d.time).getTime() > start
        )
        const pnlStart = chartData[chartData.length - 1].pnl
        const perpPnlStart = chartData[chartData.length - 1].perp_pnl
        for (let i = 0; i < chartData.length; i++) {
          if (i === chartData.length - 1) {
            chartData[i].pnl = 0
            chartData[i].perp_pnl = 0
          } else {
            chartData[i].pnl = chartData[i].pnl - pnlStart
            chartData[i].perp_pnl = chartData[i].perp_pnl - perpPnlStart
          }
        }
        setChartData(chartData.reverse())
      }
    } else {
      setChartData([])
    }
  }, [hourlyPerformanceStats, performanceRange])

  useEffect(() => {
    if (chartData.length > 0) {
      for (const stat of chartData) {
        stat.spot_pnl = stat.pnl - stat.perp_pnl
      }
    }
  }, [chartData])

  const handleMouseMove = (coords) => {
    if (coords.activePayload) {
      setMouseData(coords.activePayload[0].payload)
    }
  }

  const handleMouseLeave = () => {
    setMouseData(null)
  }

  const renderPnlChartTitle = () => {
    if (showPerpPnl && showSpotPnl) {
      return t('pnl')
    }
    if (!showSpotPnl) {
      return `${t('perp')} ${t('pnl')}`
    }
    if (!showPerpPnl) {
      return `${t('spot')} ${t('pnl')}`
    }
  }

  const formatDateAxis = (date) => {
    if (['3m', '30d'].includes(performanceRange)) {
      return dayjs(date).format('D MMM')
    } else if (performanceRange === '7d') {
      return dayjs(date).format('ddd, h:mma')
    } else {
      return dayjs(date).format('h:mma')
    }
  }

  const pnlChartDataKey = () => {
    if (!showPerpPnl && showSpotPnl) {
      return 'spot_pnl'
    } else if (!showSpotPnl && showPerpPnl) {
      return 'perp_pnl'
    } else {
      return 'pnl'
    }
  }

  const pnlChartColor =
    chartToShow === 'PnL' &&
    chartData.length > 0 &&
    chartData[chartData.length - 1][pnlChartDataKey()] > 0
      ? theme === 'Mango'
        ? '#AFD803'
        : '#5EBF4D'
      : theme === 'Mango'
      ? '#F84638'
      : '#CC2929'

  return (
    <div className="grid grid-cols-12 lg:gap-6">
      <div className="order-2 col-span-12 lg:order-1 lg:col-span-4">
        <div className="px-3 pb-4 xl:pb-6">
          <div className="flex items-center pb-1.5">
            <div className="text-sm text-th-fgd-3">
              {chartToShow === 'Value'
                ? t('account-value')
                : renderPnlChartTitle()}{' '}
            </div>
          </div>
          {mouseData ? (
            <>
              <div className="pb-1 text-2xl font-bold text-th-fgd-1 sm:text-3xl">
                {formatUsdValue(
                  mouseData[
                    chartToShow === 'PnL' ? pnlChartDataKey() : 'account_equity'
                  ]
                )}
              </div>
              <div className="text-xs font-normal text-th-fgd-4">
                {dayjs(mouseData['time']).format('ddd MMM D YYYY, h:mma')}
              </div>
            </>
          ) : chartData.length === 0 ? (
            <>
              <div className="pb-1 text-2xl font-bold text-th-fgd-1 sm:text-3xl">
                {chartToShow === 'PnL' ? '--' : formatUsdValue(accountValue)}
              </div>
              <div className="text-xs font-normal text-th-fgd-4">
                {dayjs().format('ddd MMM D YYYY, h:mma')}
              </div>
            </>
          ) : chartData.length > 0 ? (
            <>
              <div className="pb-1 text-2xl font-bold text-th-fgd-1 sm:text-3xl">
                {chartToShow === 'PnL'
                  ? formatUsdValue(
                      chartData[chartData.length - 1][pnlChartDataKey()]
                    )
                  : formatUsdValue(accountValue)}
              </div>
              <div className="text-xs font-normal text-th-fgd-4">
                {chartToShow === 'PnL'
                  ? dayjs(chartData[chartData.length - 1]['time']).format(
                      'ddd MMM D YYYY, h:mma'
                    )
                  : dayjs().format('ddd MMM D YYYY, h:mma')}
              </div>
            </>
          ) : (
            <>
              <div className="mt-1 h-8 w-48 animate-pulse rounded bg-th-bkg-3" />
              <div className="mt-1 h-4 w-24 animate-pulse rounded bg-th-bkg-3" />
            </>
          )}
        </div>
        <div className="flex flex-col divide-y divide-th-bkg-3 border-y border-th-bkg-3 md:flex-row md:divide-y-0 md:p-3 lg:flex-col lg:divide-y lg:p-0 xl:flex-row xl:divide-y-0 xl:p-5">
          <div className="flex w-full items-center space-x-3 p-3 md:w-1/2 md:p-0 lg:w-full lg:p-3 xl:w-1/2 xl:p-0">
            <HealthHeart size={40} health={Number(maintHealthRatio)} />
            <div>
              <Tooltip
                content={
                  <div>
                    {t('tooltip-account-liquidated')}{' '}
                    <a
                      href="https://docs.mango.markets/mango-markets/health-overview"
                      target="_blank"
                      rel="noopener noreferrer"
                    >
                      {t('learn-more')}
                    </a>
                  </div>
                }
              >
                <div className="flex items-center space-x-1.5 pb-0.5">
                  <div className="text-th-fgd-3">{t('health')}</div>
                  <InformationCircleIcon className="h-5 w-5 flex-shrink-0 cursor-help text-th-fgd-4" />
                </div>
              </Tooltip>
              <div className={`text-lg font-bold text-th-fgd-1`}>
                {maintHealthRatio < 100 ? maintHealthRatio.toFixed(2) : '>100'}%
              </div>
            </div>
          </div>
          <div className="flex w-full items-center space-x-3 p-3 md:w-1/2 md:p-0 md:pl-4 lg:w-full lg:p-3 xl:w-1/2 xl:p-0">
            <ScaleIcon className="h-10 w-10 text-th-fgd-4" />
            <div>
              <div className="pb-0.5 text-th-fgd-3">{t('leverage')}</div>
              {mangoGroup && mangoCache ? (
                <div className={`text-lg font-bold text-th-fgd-1`}>
                  {mangoAccount?.getLeverage(mangoGroup, mangoCache).toFixed(2)}
                  x
                </div>
              ) : null}
            </div>
          </div>
        </div>
        <div className="flex flex-col divide-y divide-th-bkg-3 border-b border-th-bkg-3 md:flex-row md:divide-y-0 md:p-3 lg:flex-col lg:divide-y lg:p-0 xl:flex-row xl:divide-y-0 xl:p-5">
          <div className="flex w-full items-center space-x-3 p-3 md:w-1/2 md:p-0 lg:w-full lg:p-3 xl:w-1/2 xl:p-0">
            <LongShortChart chartData={longData} />
            <div>
              <Tooltip content={t('total-long-tooltip')}>
                <div className="flex items-center space-x-1.5 pb-0.5">
                  <div className="text-th-fgd-3">{t('assets')}</div>
                  <InformationCircleIcon className="h-5 w-5 flex-shrink-0 cursor-help text-th-fgd-4" />
                </div>
              </Tooltip>
              {mangoGroup && mangoCache ? (
                <div className="text-lg font-bold text-th-fgd-1">
                  {formatUsdValue(+longExposure)}
                </div>
              ) : null}
            </div>
          </div>
          <div className="flex w-full items-center space-x-3 p-3 md:w-1/2 md:p-0 md:pl-4 lg:w-full lg:p-3 xl:w-1/2 xl:p-0">
            <LongShortChart chartData={shortData} />
            <div>
              <Tooltip content={t('total-short-tooltip')}>
                <div className="flex items-center space-x-1.5 pb-0.5">
                  <div className="whitespace-nowrap text-th-fgd-3">
                    {t('liabilities')}
                  </div>
                  <InformationCircleIcon className="h-5 w-5 flex-shrink-0 cursor-help text-th-fgd-4" />
                </div>
              </Tooltip>
              {mangoGroup && mangoCache ? (
                <div className="text-lg font-bold text-th-fgd-1">
                  {formatUsdValue(+shortExposure)}
                </div>
              ) : null}
            </div>
          </div>
        </div>
      </div>
      <div className="order-1 col-span-12 px-4 pb-6 lg:order-2 lg:col-span-8 lg:pb-0 xl:px-6">
        <div className="mb-4 flex justify-between space-x-2 sm:mb-6">
          <div className="flex flex-col sm:flex-row sm:items-center sm:space-x-3">
            <div className="mb-3 w-28 sm:mb-0">
              <ButtonGroup
                activeValue={chartToShow}
                className="h-8"
                onChange={(c) => setChartToShow(c)}
                values={['Value', 'PnL']}
              />
            </div>
            {chartToShow === 'PnL' && chartData.length ? (
              <div className="flex space-x-3">
                <Checkbox
                  checked={showSpotPnl}
                  disabled={!showPerpPnl}
                  onChange={(e) => setShowSpotPnl(e.target.checked)}
                >
                  {t('include-spot')}
                </Checkbox>
                <Checkbox
                  checked={showPerpPnl}
                  disabled={!showSpotPnl}
                  onChange={(e) => setShowPerpPnl(e.target.checked)}
                >
                  {t('include-perp')}
                </Checkbox>
              </div>
            ) : null}
          </div>
          <div className="w-40">
            <ButtonGroup
              activeValue={performanceRange}
              className="h-8"
              onChange={(p) => setPerformanceRange(p)}
              values={performanceRangePresetLabels}
            />
          </div>
        </div>
        {chartData.length > 0 ? (
          <div className="h-48 md:h-64 lg:h-[340px] xl:h-[225px]" ref={observe}>
            <AreaChart
              width={width}
              height={height + 12}
              data={chartData?.length ? chartData : defaultData}
              onMouseMove={handleMouseMove}
              onMouseLeave={handleMouseLeave}
            >
              <ChartTooltip
                cursor={{
                  strokeOpacity: 0,
                }}
                content={<></>}
              />

              <defs>
                <linearGradient
                  id="defaultGradientArea"
                  x1="0"
                  y1="0"
                  x2="0"
                  y2="1"
                >
                  <stop offset="0%" stopColor="#ffba24" stopOpacity={0.9} />
                  <stop offset="80%" stopColor="#ffba24" stopOpacity={0} />
                </linearGradient>
                <linearGradient
                  id="greenGradientArea"
                  x1="0"
                  y1="0"
                  x2="0"
                  y2="1"
                >
                  <stop
                    offset="0%"
                    stopColor={theme === 'Mango' ? '#AFD803' : '#5EBF4D'}
                    stopOpacity={0.9}
                  />
                  <stop
                    offset="80%"
                    stopColor={theme === 'Mango' ? '#AFD803' : '#5EBF4D'}
                    stopOpacity={0}
                  />
                </linearGradient>
                <linearGradient
                  id="redGradientArea"
                  x1="0"
                  y1="1"
                  x2="0"
                  y2="0"
                >
                  <stop
                    offset="0%"
                    stopColor={theme === 'Mango' ? '#F84638' : '#CC2929'}
                    stopOpacity={0.9}
                  />
                  <stop
                    offset="80%"
                    stopColor={theme === 'Mango' ? '#F84638' : '#CC2929'}
                    stopOpacity={0}
                  />
                </linearGradient>
              </defs>
              <Area
                isAnimationActive={true}
                type="monotone"
                dataKey={
                  chartToShow === 'PnL' ? pnlChartDataKey() : 'account_equity'
                }
                stroke={chartToShow === 'PnL' ? pnlChartColor : '#ffba24'}
                fill={
                  chartToShow === 'PnL'
                    ? chartData[chartData.length - 1][pnlChartDataKey()] > 0
                      ? 'url(#greenGradientArea)'
                      : 'url(#redGradientArea)'
                    : 'url(#defaultGradientArea)'
                }
                fillOpacity={0.3}
              />

              <YAxis
                dataKey={
                  chartToShow === 'PnL' ? pnlChartDataKey() : 'account_equity'
                }
                type="number"
                domain={['dataMin', 'dataMax']}
                axisLine={false}
                dx={-10}
                tick={{
                  fill:
                    theme === 'Light'
                      ? 'rgba(0,0,0,0.4)'
                      : 'rgba(255,255,255,0.35)',
                  fontSize: 10,
                }}
                tickLine={false}
                tickFormatter={(v) => numberCompacter.format(v)}
              />
              <XAxis
                dataKey="time"
                axisLine={false}
                dy={10}
                minTickGap={20}
                tick={{
                  fill:
                    theme === 'Light'
                      ? 'rgba(0,0,0,0.4)'
                      : 'rgba(255,255,255,0.35)',
                  fontSize: 10,
                }}
                tickLine={false}
                tickFormatter={(v) => formatDateAxis(v)}
              />
            </AreaChart>
          </div>
        ) : (
          <div className="flex h-48 w-full items-center justify-center rounded-md bg-th-bkg-3 md:h-64 lg:h-[410px] xl:h-[270px]">
            <p className="mb-0">{t('no-chart')}</p>
          </div>
        )}
      </div>
    </div>
  )
}

export default AccountOverviewStats
