import { Box, Card, CardProps, Group, Loader, Paper, ScrollArea, Skeleton, Stack, Typography } from '@tidbcloud/uikit'
import { IconCheckCircle } from '@tidbcloud/uikit/icons'
// import { Link } from 'react-router-dom'

import { PropertyKV } from 'dbaas/components'
import { SharedCluster } from 'dbaas/features/ClusterManagement/cluster'
import { renderNodes } from 'dbaas/features/ClusterManagement/common'
import { renderTiproxy } from 'dbaas/features/ClusterManagement/dedicated/node/NodeSizes/TiProxy'
import { CloudProviderConst } from 'dbaas/features/Project'
import { renderStorageType } from 'dbaas/screens/ClustersV2/new/helpers'
import { CentralClusterStatus } from 'dbaas/services/api-clients/legacy/central/interface'
import {
  ClusterStorageNodeSettingStorageType,
  Commonv1beta1ClusterState
} from 'dbaas/services/api-clients/v2023/dedicated/v1beta1/interface'

import { renderSpecVersion, useBFFDedicated, useSpecVersionEnabled } from '../helpers'

const getModifyingProgressDesc = (expectedQuantity?: number, uptodateQuantity?: number, pending?: boolean) => {
  if (pending) {
    return 'Collecting progress...'
  }

  const expectedCount = expectedQuantity || 0
  const upToDateCount = uptodateQuantity || 0
  const expectedDesc = `Expect ${expectedCount} ${expectedCount > 1 ? 'nodes' : 'node'}`
  const upToDateDesc = `${upToDateCount} ${expectedCount > 1 ? 'of them' : ''} ${
    upToDateCount > 1 ? 'are' : 'is'
  } up to date`

  return `${expectedDesc}, ${upToDateDesc}.`
}

const getDeletingProgressDesc = (deletionQuantity?: number, pending?: boolean) => {
  if (pending) {
    return 'Collecting progress...'
  }

  const count = deletionQuantity || 0

  return `Remaining ${count} ${count > 1 ? 'nodes are' : 'node is'} being deleted.`
}

const NodeModifyingDesc = ({
  status,
  progress,
  expectedQuantity,
  uptodateQuantity,
  deletionQuantity,
  pending
}: {
  status?: CentralClusterStatus | Commonv1beta1ClusterState
  progress: boolean
  expectedQuantity?: number
  uptodateQuantity?: number
  deletionQuantity?: number
  pending?: boolean
}) => {
  const isModifying = status === CentralClusterStatus.SCALING || status === Commonv1beta1ClusterState.MODIFYING

  if (!isModifying || !progress) {
    return null
  }

  const done = !pending && expectedQuantity === uptodateQuantity

  return (
    <Paper shadow="none" px="md" py={8} bg="carbon.2">
      <Stack>
        <Group>
          {done ? <Box component={IconCheckCircle} size={16} c="green" /> : <Loader size={16} />}
          <Typography variant="label-lg">
            {getModifyingProgressDesc(expectedQuantity, uptodateQuantity, pending)}
          </Typography>
        </Group>
        {!!deletionQuantity && (
          <Group>
            <Loader size={16} />
            <Typography variant="label-lg">{getDeletingProgressDesc(deletionQuantity, pending)}</Typography>
          </Group>
        )}
      </Stack>
    </Paper>
  )
}

const NodeProfileName = ({ children }: React.PropsWithChildren<{}>) => {
  if (!children) {
    return null
  }

  return <Box>{children}</Box>
}

interface ClusterSizePanelProps extends Omit<CardProps, 'children'> {
  cluster: SharedCluster
  loading?: boolean
}

export const ClusterSizePanel = ({ cluster, loading, ...rootProps }: ClusterSizePanelProps) => {
  const { dedicated, isLoading, useBffData } = useBFFDedicated(cluster)
  const tidbNodeSetting = dedicated?.tidbNodeSetting
  const tikvNodeSetting = dedicated?.tikvNodeSetting
  const tiflashNodeSetting = dedicated?.tiflashNodeSetting

  const { specVersionEnabled } = useSpecVersionEnabled(cluster.provider || '')
  return (
    <ScrollArea.Autosize mah={800}>
      <Card p="xl" {...rootProps}>
        <Group justify="space-between" mb="md">
          <Typography variant="headline-sm">Cluster Size</Typography>
          {/* TODO:
          the "more" button will be enabled
          once the new node map UI is available
        */}
          {/* {!loading && (
          <Button
            variant="default"
            size="xs"
            component={Link}
            to={`/clusters/${cluster.id}/node-map`}
            sx={(theme) => ({
              '&:hover': {
                textDecoration: 'none',
                color: theme.colors.carbon[8]
              }
            })}
            data-mp-event="Cluster Size More Button Clicked"
          >
            More
          </Button>
        )} */}
        </Group>
        {isLoading && (
          <Stack gap="sm">
            <Skeleton h={20} /> <Skeleton h={20} /> <Skeleton h={20} />
          </Stack>
        )}
        {!isLoading && useBffData && dedicated && (
          <Stack justify="flex-start" gap={4}>
            {tidbNodeSetting?.tidbNodeGroups.map((v, i) => (
              <Stack key={v.tidbNodeGroupId}>
                <PropertyKV key={v.tidbNodeGroupId} label={i === 0 ? 'TiDB' : ''} labelProps={{ w: 128 }}>
                  <Stack justify="flex-start" gap={4}>
                    {i === 0 && (
                      <NodeProfileName>
                        {v.nodeSpecDisplayName}
                        {renderSpecVersion(v.nodeSpecVersion, specVersionEnabled)}
                      </NodeProfileName>
                    )}
                    <Box>
                      {v.displayName} : {renderNodes(v.nodeCount)}
                    </Box>
                    {renderTiproxy(v.tiproxySetting)}
                    <NodeModifyingDesc
                      status={dedicated.state}
                      progress={!!v.tiproxyNodeChangingProgress}
                      expectedQuantity={v.tiproxySetting?.nodeCount ?? 0}
                      uptodateQuantity={v.tiproxyNodeChangingProgress?.matchingNodeSpecNodeCount}
                      deletionQuantity={v.tiproxyNodeChangingProgress?.remainingDeletionNodeCount}
                    />
                  </Stack>
                </PropertyKV>
                <NodeModifyingDesc
                  status={dedicated.state}
                  progress={!!v.nodeChangingProgress}
                  expectedQuantity={v.nodeCount}
                  uptodateQuantity={v.nodeChangingProgress?.matchingNodeSpecNodeCount}
                  deletionQuantity={v.nodeChangingProgress?.remainingDeletionNodeCount}
                />
              </Stack>
            ))}
            <PropertyKV label="TiKV" labelProps={{ w: 128 }} my="xs">
              <Stack justify="flex-start" gap={4}>
                <NodeProfileName>
                  {tikvNodeSetting?.nodeSpecDisplayName}
                  {renderSpecVersion(tikvNodeSetting?.nodeSpecVersion, specVersionEnabled)}
                </NodeProfileName>
                <Box>
                  {tikvNodeSetting?.storageSizeGi || 0} GiB Storage × {renderNodes(tikvNodeSetting?.nodeCount ?? 0)}
                </Box>
                {cluster.provider === CloudProviderConst.AWS && (
                  <Box>{renderStorageType(tikvNodeSetting?.storageType)} Storage</Box>
                )}
                {tikvNodeSetting?.storageType === ClusterStorageNodeSettingStorageType.Performance && (
                  <Box>{tikvNodeSetting?.raftStoreIops || 0} Extra Raft IOPS</Box>
                )}
              </Stack>
            </PropertyKV>
            <NodeModifyingDesc
              status={dedicated.state}
              progress={!!tikvNodeSetting?.nodeChangingProgress}
              expectedQuantity={tikvNodeSetting?.nodeCount}
              uptodateQuantity={tikvNodeSetting?.nodeChangingProgress?.matchingNodeSpecNodeCount}
              deletionQuantity={tikvNodeSetting?.nodeChangingProgress?.remainingDeletionNodeCount}
            />

            {!!tiflashNodeSetting?.nodeCount && (
              <>
                <PropertyKV label="TiFlash" labelProps={{ w: 128 }} mb="xs">
                  <Stack justify="flex-start" gap={4}>
                    <NodeProfileName>
                      {tiflashNodeSetting.nodeSpecDisplayName}
                      {renderSpecVersion(tiflashNodeSetting.nodeSpecVersion, specVersionEnabled)}
                    </NodeProfileName>
                    <Box></Box>
                    <Box>
                      {tiflashNodeSetting.storageSizeGi || 0} GiB Storage × {renderNodes(tiflashNodeSetting.nodeCount)}
                    </Box>
                    {cluster.provider === CloudProviderConst.AWS && (
                      <Box>{renderStorageType(tiflashNodeSetting?.storageType)} Storage</Box>
                    )}
                  </Stack>
                </PropertyKV>
                <NodeModifyingDesc
                  status={dedicated.state}
                  progress={!!tiflashNodeSetting?.nodeChangingProgress}
                  expectedQuantity={tiflashNodeSetting?.nodeCount}
                  uptodateQuantity={tiflashNodeSetting?.nodeChangingProgress?.matchingNodeSpecNodeCount}
                  deletionQuantity={tiflashNodeSetting?.nodeChangingProgress?.remainingDeletionNodeCount}
                />
              </>
            )}
          </Stack>
        )}
      </Card>
    </ScrollArea.Autosize>
  )
}
