import { Card, Divider, Group, Stack, Typography } from '@tidbcloud/uikit'
import clsx from 'clsx'
import { groupBy } from 'lodash-es'
import { observer } from 'mobx-react'
import React from 'react'

import Link from 'dbaas/components/Link'
import { COMPONENT_TYPE_DICT } from 'dbaas/screens/ClusterForm/utils'
import { CalcClusterFeeRespComponentCost, CentralComponentType } from 'dbaas/services'
import useStores from 'dbaas/stores/useStores'
import { precision } from 'dbaas/utils/format'

interface FeeItemProps {
  name: string | React.ReactNode
  price: number | string
  isPoints?: boolean
  isTotal?: boolean
}

export function processPrecision(amount: number | string, fixed = 4) {
  if (isNaN(Number(amount))) return NaN

  return Math.floor(Number(amount) * Math.pow(10, fixed)) / Math.pow(10, fixed)
}

export const MoneyValue = ({
  className,
  amount,
  fixed = 4,
  isPoints = false,
  withPrecision = true
}: {
  className?: string
  amount: number | string | null
  fixed?: number
  isPoints?: boolean
  withPrecision?: boolean
}) => {
  const num = Number(amount)
  return amount === null || isNaN(num) ? (
    <span className="value">-</span>
  ) : (
    <span className={clsx('value', className)}>
      $ {isPoints ? num / 100 : withPrecision ? processPrecision(num, fixed) : num}
    </span>
  )
}

export function getTotalCost(costs: CalcClusterFeeRespComponentCost[], isDevTier?: boolean) {
  if (!costs || !costs.length) return null

  const sum = costs.reduce(
    (previousValue, currentValue) =>
      precision(
        previousValue +
          (isDevTier
            ? processPrecision(currentValue.compute || 0) + processPrecision(currentValue.storage || 0)
            : processPrecision(currentValue.raw_compute || 0) + processPrecision(currentValue.raw_storage || 0))
      ),
    0
  )
  return sum
}

const FeeItem: React.FC<React.PropsWithChildren<FeeItemProps>> = ({ name, price, isTotal }) => (
  <Group justify="space-between">
    <Typography variant="body-lg">{name}</Typography>
    <MoneyValue amount={price} withPrecision={!isTotal} />
  </Group>
)

export default observer(
  ({ costs, isDevTier }: { costs: CalcClusterFeeRespComponentCost[]; isDevTier?: boolean; isPoints?: boolean }) => {
    const costMap = groupBy(costs, 'component_type')
    const tidbCost = costMap[CentralComponentType.COMPONENT_TYPE_TIDB]?.[0]
    const tikvCost = costMap[CentralComponentType.COMPONENT_TYPE_TIKV]?.[0]
    const tiflashCost = costMap[CentralComponentType.COMPONENT_TYPE_TIFLASH]?.[0]
    const planCost = getTotalCost(costs, isDevTier) || 0

    const {
      store: { activeProject }
    } = useStores()

    return (
      <Stack>
        <Stack>
          <Stack gap={8}>
            <Typography variant="headline-sm">TiDB Cost</Typography>
            <FeeItem name="Compute Cost" price={isDevTier ? tidbCost?.compute : tidbCost?.raw_compute} />
          </Stack>

          <Divider />

          <Stack gap={8}>
            <Typography variant="headline-sm">TiKV Cost</Typography>
            <FeeItem name="Compute Cost" price={isDevTier ? tikvCost?.compute : tikvCost?.raw_compute} />
            <FeeItem name="Storage Cost" price={isDevTier ? tikvCost?.storage : tikvCost?.raw_storage} />
            <FeeItem
              name="TiKV Cost"
              price={
                isDevTier
                  ? precision(processPrecision(tikvCost?.compute) + processPrecision(tidbCost?.storage))
                  : precision(processPrecision(tikvCost?.raw_compute) + processPrecision(tikvCost?.raw_storage))
              }
              isTotal
            />
          </Stack>

          <Divider />

          {tiflashCost && (
            <Stack gap={8}>
              <Typography variant="headline-sm">
                {COMPONENT_TYPE_DICT[CentralComponentType.COMPONENT_TYPE_TIFLASH]} Cost
              </Typography>
              <FeeItem name="Compute Cost" price={isDevTier ? tiflashCost?.compute : tiflashCost?.raw_compute} />
              <FeeItem name="Storage Cost" price={isDevTier ? tiflashCost?.storage : tiflashCost?.raw_storage} />
              <FeeItem
                name={<>{COMPONENT_TYPE_DICT[CentralComponentType.COMPONENT_TYPE_TIFLASH]} Cost</>}
                price={
                  isDevTier
                    ? precision(processPrecision(tiflashCost?.compute) + processPrecision(tiflashCost?.storage))
                    : precision(processPrecision(tiflashCost?.raw_compute) + processPrecision(tiflashCost?.raw_storage))
                }
                isTotal
              />
            </Stack>
          )}
        </Stack>

        <Stack gap={8}>
          <Typography variant="headline-sm">Plan Cost</Typography>
          <Card
            shadow="unset"
            bg="peacock.2"
            withBorder={false}
            sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}
          >
            <div>
              <Typography variant="title-lg">{isDevTier ? 'Developer' : 'Dedicated'} Tier</Typography>
              {isDevTier ? (
                <Typography variant="body-md">Try and test our features.</Typography>
              ) : (
                <Typography variant="body-md">Your dedicated cluster.</Typography>
              )}
            </div>
            <div>
              <MoneyValue amount={planCost} withPrecision={false} /> /hour
            </div>
          </Card>

          {!activeProject.is_cross_account && (
            <Typography variant="body-md">
              See the detailed{' '}
              <Link
                href="https://en.pingcap.com/tidb-cloud-pricing/"
                target="_blank"
                rel="noreferrer"
                eventName="Node Price Link Clicked"
                eventParams={{ source: 'Cluster Fee' }}
              >
                Node Price
              </Link>
              .
            </Typography>
          )}
        </Stack>
      </Stack>
    )
  }
)
