import {
  ActionIcon,
  Anchor,
  Badge,
  Box,
  Button,
  Flex,
  Group,
  HoverCard,
  Input,
  Menu,
  Modal,
  Stack,
  Typography
} from '@tidbcloud/uikit'
import { Form, MRT_ColumnDef, ProTable } from '@tidbcloud/uikit/biz'
import {
  IconDotsHorizontal,
  IconEdit03,
  IconInfoCircle,
  IconSearchLg,
  IconTrash01
} from '@tidbcloud/uikit/icons'
import { useMemo, useState } from 'react'
import { Link, useHistory, useParams } from 'react-router-dom'

import { useDeleteBudget, useListAllBudgets } from 'apiClient/services/billing'
import {
  FormsBillingConfig,
  FormsBudget
} from 'apiClient/services/billing/interface'
import { capitalize } from 'utils/string'

import { MoneyValue } from '../components/MoneyValue'
import { toFloorPriceStr } from '../components/utils'

const MAX_CUSTOM_BUDGET_SIZE = 5
const EMPTY_ARR: FormsBudget[] = []
const BIZ_TYPE_MAP: { [k: string]: string } = {
  serverless_cluster: 'Serverless Spending Limit',
  budget_alert: 'Custom'
}
const STATUS_MAP: { [k: string]: string } = {
  fit: 'OK',
  warning: 'Warning',
  excessive: 'Exceeded'
}
const SCOPE_MAP: { [k: string]: string } = {
  tenant: 'Organization',
  cluster: 'Cluster',
  project: 'Project'
}

export const BudgetAlert: React.FC<
  React.PropsWithChildren<{ billingConfig?: FormsBillingConfig }>
> = ({ billingConfig }) => {
  const history = useHistory()
  const { org_id: orgId } = useParams<{ org_id: string }>()
  const org_id = billingConfig?.tenant_id || orgId
  const {
    data: dataResp,
    isLoading: isLoadingList,
    isRefetching
  } = useListAllBudgets(org_id, {
    query: { refetchOnWindowFocus: false }
  })
  const data = dataResp?.data
  const [search, setSearch] = useState('')
  const searchedData = useMemo(() => {
    const _data = data || []
    const _search = search.trim()
    if (!_search) {
      return _data
    }

    return _data.filter((d) =>
      d.name?.toLowerCase().includes(_search.toLowerCase())
    )
  }, [search, data])
  const isLoading = isLoadingList || isRefetching
  const customBudgets = useMemo(
    () => data?.filter((d) => d.biz_type !== DEFAULT_BUDGET_TYPE),
    [data]
  )

  return (
    <Stack>
      <Group justify="space-between">
        <Input
          rightSection={
            <Flex
              w={36}
              h={36}
              justify="center"
              align="center"
              sx={{ cursor: 'pointer' }}
            >
              <IconSearchLg />
            </Flex>
          }
          w={298}
          value={search}
          onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
            setSearch(e.currentTarget.value)
          }
        />
        {/* <Button
          h={32}
          disabled={
            isLoading || (customBudgets?.length || 0) >= MAX_CUSTOM_BUDGET_SIZE
          }
          onClick={() => {
            history.push('/console/org-settings/billing/budget-alert/budget')
          }}
          data-mp-event="Create Budget Button Clicked"
        >
          Create Custom Budget{' '}
          {isLoading
            ? ''
            : `(${customBudgets?.length || 0}/${MAX_CUSTOM_BUDGET_SIZE})`}
        </Button> */}
      </Group>
      <BudgetAlertTable
        data={searchedData}
        isLoading={isLoading}
        errorMessage={''}
        orgId={org_id}
      />
    </Stack>
  )
}

const BudgetAlertTable: React.FC<
  React.PropsWithChildren<{
    data?: FormsBudget[]
    isLoading: boolean
    errorMessage: string
    orgId: string
  }>
> = ({ data, isLoading, errorMessage, orgId }) => {
  const [deleteModalData, setDeleteModalData] = useState<FormsBudget>()

  const clusterColumns: MRT_ColumnDef<FormsBudget>[] = useMemo(
    () => [
      {
        accessorKey: 'name',
        header: 'Name',
        minSize: 160,
        accessorFn: (row) => {
          // if (row.biz_type === 'serverless_cluster' && row.meta?.cluster_name) {
          //   return (
          //     <Typography>
          //       Budget for{' '}
          //       <Link
          //         to=""
          //         onClick={(e) => {
          //           e.preventDefault()
          //           window.location.href = `/console/clusters/${
          //             row.meta!.cluster_id
          //           }/overview?orgId=${orgId}&projectId=${row.meta!.project_id}`
          //           return false
          //         }}
          //       >
          //         {row.meta.cluster_name}
          //       </Link>
          //     </Typography>
          //   )
          // }
          return row.name
        }
      },
      {
        header: 'Type',
        Header: () => {
          return (
            <Group gap="xs">
              <Typography>Type</Typography>
              <HoverCard position="top" shadow="md" withArrow withinPortal>
                <HoverCard.Target>
                  <Group sx={{ cursor: 'pointer' }}>
                    <IconInfoCircle />
                  </Group>
                </HoverCard.Target>
                <HoverCard.Dropdown>
                  The spending limit budget is automatically created according
                  to the{' '}
                  <Anchor
                    href="https://docs.pingcap.com/tidbcloud/manage-serverless-spend-limit"
                    target="_blank"
                  >
                    spending limit
                  </Anchor>{' '}
                  configured for your TiDB Serverless scalable cluster.
                </HoverCard.Dropdown>
              </HoverCard>
            </Group>
          )
        },
        accessorFn: (row) =>
          row.biz_type ? BIZ_TYPE_MAP[row.biz_type] : 'Unknown',
        size: 200
      },
      {
        header: 'Status',
        accessorFn: (row) => <StateTag data={row} />,
        size: 210
      },
      {
        header: 'Amount Used',
        accessorFn: (row) => {
          return <MoneyValue amount={row.costs!} />
          // const bizData = JSON.parse(row.biz_data || '{}')
          // const withDiscountAndCredit = (!bizData.apply_credits ||
          //   !bizData.apply_discounts) as boolean
          // let filterParams: { [k: string]: any } = {}

          // if (withDiscountAndCredit) {
          //   filterParams.withDiscountAndCredit = true
          // }
          // const isServerless = row.biz_type === 'serverless_cluster'
          // const isCustomAndProjectRange =
          //   row.biz_type === 'budget_alert' && row.range_type === 'project'
          // if (isServerless) {
          //   filterParams.cluster = [row.range_id_str]
          // }
          // if (isCustomAndProjectRange) {
          //   filterParams.project = [row.range_id_str]
          // }

          // const filterParamsStr = JSON.stringify(filterParams)

          // return (
          //   <HoverCard position="top" shadow="md" withArrow withinPortal>
          //     <HoverCard.Target>
          //       <Link
          //         to={`/console/org-settings/billing/cost-explorer?&__ce_filter__=${filterParamsStr}`}
          //         aria-label="go to"
          //       >
          //         <MoneyValue amount={row.costs!} />
          //       </Link>
          //     </HoverCard.Target>
          //     <HoverCard.Dropdown>
          //       Analyze your costs with Cost Explorer.
          //     </HoverCard.Dropdown>
          //   </HoverCard>
          // )
        },
        size: 160
      },
      {
        header: 'Budget Amount',
        accessorFn: (row) => <MoneyValue amount={row.limit!} />,
        size: 160
      },
      {
        accessorKey: 'interval',
        header: 'Period',
        size: 100,
        accessorFn: (row) => capitalize(row.interval!)
      },
      {
        accessorKey: 'range_type',
        header: 'Scope',
        size: 110,
        accessorFn: (row) => SCOPE_MAP[row.range_type!]
      }
      // {
      //   header: 'Action',
      //   accessorFn: (row) => {
      //     return (
      //       <BudgetOperations
      //         data={row}
      //         openDeleteModal={() => setDeleteModalData(row)}
      //       />
      //     )
      //   },
      //   size: 60
      // }
    ],
    []
  )

  return (
    <>
      <Box>
        <ProTable<FormsBudget>
          loading={isLoading}
          errorMessage={errorMessage}
          enablePinning
          initialState={{ columnPinning: { left: ['name'] } }}
          mantineTableProps={{
            verticalSpacing: 'sm',
            horizontalSpacing: 'sm',
            sx: {
              'thead tr th:first-of-type': {
                paddingLeft: 24
              }
            }
          }}
          mantinePaperProps={{
            sx: {
              borderRadius: 0,
              borderLeftWidth: 0,
              borderRightWidth: 0
            }
          }}
          columns={clusterColumns}
          data={data || EMPTY_ARR}
          emptyMessage="No Data."
        />
      </Box>
      <DeleteBudgetModal
        visible={!!deleteModalData}
        onClose={() => setDeleteModalData(undefined)}
        budget={deleteModalData}
        orgId={orgId}
      />
    </>
  )
}

const statusColorMap: {
  [index: string]: string
} = {
  fit: 'green',
  excessive: 'red'
}
const StateTag: React.FC<React.PropsWithChildren<{ data: FormsBudget }>> = ({
  data
}) => {
  const proportion =
    (Number.parseFloat(data.costs!) / Number.parseFloat(data.limit!)) * 100
  const proportionStr = proportion.toFixed(2)
  const status = data.status

  let statusLabel = STATUS_MAP[status!] || status
  let statusColor = statusColorMap[status || '']

  const minThreshold =
    data.thresholds?.reduce((prev, cur) => {
      const curProportion = Number.parseFloat(cur.proportion!) * 100
      if (!prev) {
        return curProportion
      }

      if (curProportion < prev) {
        return curProportion
      }

      return prev
    }, 0) || 0

  if (status === 'fit' && proportion >= minThreshold) {
    statusLabel = STATUS_MAP.warning
    statusColor = 'yellow'
  }

  return (
    <Group gap="xs">
      <Badge color={statusColor} variant="dot" size="lg" sx={{ padding: 0 }}>
        {statusLabel} ({proportionStr}%)
      </Badge>
      <HoverCard
        position="right"
        shadow="md"
        width={280}
        withArrow
        withinPortal
      >
        <HoverCard.Target>
          <Stack align="center" sx={{ cursor: 'pointer' }}>
            <IconInfoCircle />
          </Stack>
        </HoverCard.Target>
        <HoverCard.Dropdown>
          <Stack gap="xs">
            {data.thresholds?.map((t, idx) => {
              const tProportion = Number.parseFloat(t.proportion!)
              return (
                <Typography variant="body-sm">
                  Threshold {idx + 1}: {'>='} {(tProportion * 100).toFixed(2)}%
                  (
                  {toFloorPriceStr(
                    Number.parseFloat(data.limit!) * tProportion
                  )}
                  ) {proportion >= tProportion * 100 ? 'exceeded' : ''}
                </Typography>
              )
            })}
          </Stack>
        </HoverCard.Dropdown>
      </HoverCard>
    </Group>
  )
}

const DEFAULT_BUDGET_TYPE = 'serverless_cluster'

const BudgetOperations: React.FC<
  React.PropsWithChildren<{
    data: FormsBudget
    openDeleteModal: () => void
  }>
> = ({ data, openDeleteModal }) => {
  const history = useHistory()
  return (
    <Menu position="bottom-end" width={200} withinPortal>
      <Menu.Target>
        <ActionIcon
          variant="default"
          data-mp-event="Budget Detail Button Clicked"
          w={32}
          h={32}
        >
          <IconDotsHorizontal size={16} />
        </ActionIcon>
      </Menu.Target>
      <Menu.Dropdown>
        <HoverCard
          position="left"
          shadow="md"
          width={220}
          withArrow
          disabled={data.biz_type !== DEFAULT_BUDGET_TYPE}
        >
          <HoverCard.Target>
            <Menu.Item
              leftSection={<IconEdit03 size={20} />}
              data-mp-event="Edit Budget Button Clicked"
              onClick={() =>
                data.biz_type !== DEFAULT_BUDGET_TYPE &&
                history.push(
                  `/console/org-settings/billing/budget-alert/budget/${data.spendlimit_setting_id}`
                )
              }
              {...(data.biz_type === DEFAULT_BUDGET_TYPE
                ? { 'data-disabled': true }
                : {})}
            >
              Edit
            </Menu.Item>
          </HoverCard.Target>
          <HoverCard.Dropdown>
            You can edit spending limit on serverless cluster overview page.
          </HoverCard.Dropdown>
        </HoverCard>
        <HoverCard
          position="left"
          shadow="md"
          width={220}
          withArrow
          disabled={data.biz_type !== DEFAULT_BUDGET_TYPE}
        >
          <HoverCard.Target>
            <Menu.Item
              leftSection={<IconTrash01 size={20} />}
              data-mp-event="Delete Budget Button Clicked"
              onClick={() =>
                data.biz_type !== DEFAULT_BUDGET_TYPE && openDeleteModal()
              }
              {...(data.biz_type === DEFAULT_BUDGET_TYPE
                ? { 'data-disabled': true }
                : {})}
            >
              Delete
            </Menu.Item>
          </HoverCard.Target>
          <HoverCard.Dropdown>
            You cannot delete the spending limit for a serverless scalable
            cluster.
          </HoverCard.Dropdown>
        </HoverCard>
      </Menu.Dropdown>
    </Menu>
  )
}

const DeleteBudgetModal: React.FC<
  React.PropsWithChildren<{
    visible: boolean
    onClose: () => void
    budget?: FormsBudget
    orgId: string
  }>
> = ({ visible, onClose, budget, orgId }) => {
  const { mutateAsync: deleteBudget, isLoading } = useDeleteBudget()
  const { refetch: refreshList } = useListAllBudgets(orgId, {
    query: { enabled: false }
  })

  return (
    <Modal
      size="xl"
      opened={visible}
      centered
      trapFocus={false}
      onClose={onClose}
      title={<>Delete {budget?.name}</>}
    >
      <Typography variant="body-lg">
        Are you sure you want to delete this budget alert? Once deleted, you
        will no longer receive over-limit notifications.
      </Typography>

      <Form
        layout="none"
        form={undefined}
        onSubmit={async () => {
          await deleteBudget({
            tenantId: orgId,
            budgetId: String(budget?.spendlimit_setting_id!)
          })
          refreshList()
          onClose()
        }}
        onCancel={onClose}
        actionsProps={{
          loading: isLoading,
          confirmText: 'I understand, delete it.',
          confirmProps: {
            color: 'red',
            'data-mp-event': 'Deleted A Budget Alert Config'
          },
          cancelProps: {
            'data-mp-event': 'Cancel Delete Budget Alert Modal Button Clicked'
          }
        }}
      />
    </Modal>
  )
}
