import { Box, Flex } from '@tidbcloud/uikit'
import { groupBy, map } from 'lodash-es'
import { observer } from 'mobx-react'
import { FormProvider, useForm } from 'react-hook-form'

import { TIDB_DEFAULT_NODE_COUNT, TIKV_DEFAULT_NODE_COUNT } from 'dbaas/features/ClusterManagement/dedicated'
import { CloudProvider, CloudProviderConst } from 'dbaas/features/Project'
import { useClusterServiceGetCluster } from 'dbaas/services/api-clients/v2023/cluster-management/v1beta1'
import { TidbCloudOpenApidedicatedv1beta1Cluster } from 'dbaas/services/api-clients/v2023/cluster-management/v1beta1/interface'
import { useRegionServiceListNodeSpecs } from 'dbaas/services/api-clients/v2023/dedicated/v1beta1'
import { Dedicatedv1beta1ComponentType } from 'dbaas/services/api-clients/v2023/dedicated/v1beta1/interface'
import useStores from 'dbaas/stores/useStores'

import { ClusterPageShell } from '../../components'

import { FormForTidbGroup } from './FormForTidbGroup'
import { FormModelForTidbGroup } from './helpers'
import { SumForTidbGroup } from './SumForTidbGroup'

interface ModifyingForTidbGroupProps {
  cluster: TidbCloudOpenApidedicatedv1beta1Cluster
  orgId: string
}

const ModifyingForTidbGroupInner = observer(({ cluster, orgId }: ModifyingForTidbGroupProps) => {
  const { cloudProvider = '', regionId, tidbNodeSetting, tikvNodeSetting, tiflashNodeSetting } = cluster || {}
  const defaultNodes: FormModelForTidbGroup['nodes'] = {
    tidb: {
      specKey: tidbNodeSetting?.nodeSpecKey || '',
      nodeGroups:
        tidbNodeSetting?.tidbNodeGroups?.map((group) => ({
          groupId: group.tidbNodeGroupId || '',
          displayName: group.displayName || '',
          nodeCount: group.nodeCount || TIDB_DEFAULT_NODE_COUNT,
          isDefault: !!group.isDefaultGroup,
          editMode: 'unset',
          tiproxySetting: group.tiproxySetting
        })) || []
    },
    tikv: {
      specKey: tikvNodeSetting?.nodeSpecKey || '',
      nodeCount: tikvNodeSetting?.nodeCount || TIKV_DEFAULT_NODE_COUNT,
      storageGiB: tikvNodeSetting?.storageSizeGi || 0,
      storageType: tikvNodeSetting?.storageType,
      raftStoreIops: tikvNodeSetting?.raftStoreIops ?? undefined,
      dataStoreIops: tikvNodeSetting?.dataStoreIops ?? undefined
    },
    // origin sizes of tiflash maybe `null`
    tiflash:
      (tiflashNodeSetting?.nodeCount ?? 0) > 0
        ? {
            specKey: tiflashNodeSetting?.nodeSpecKey || '',
            nodeCount: tiflashNodeSetting?.nodeCount || 0,
            storageGiB: tiflashNodeSetting?.storageSizeGi || 0,
            storageType: tiflashNodeSetting?.storageType
          }
        : {
            specKey: '',
            nodeCount: 0,
            storageGiB: 0,
            storageType: undefined
          }
  }
  const formProps = useForm<FormModelForTidbGroup>({
    mode: 'onChange',
    defaultValues: {
      nodes: defaultNodes,
      specVersion: cluster.tidbNodeSetting?.nodeSpecVersion
    }
  })

  const tidbGroupFullSupported = Array.of<CloudProvider>(CloudProviderConst.AWS, CloudProviderConst.GCP).includes(
    cloudProvider as CloudProvider
  )

  const {
    store: {
      lastVisitLocation: { projectId }
    }
  } = useStores()

  const { data: nodeSpecs, isLoading } = useRegionServiceListNodeSpecs(regionId, {
    orgId,
    projectId,
    clusterId: cluster.clusterId,
    pageSize: 99
  })

  const nodeSpecByType = map(
    groupBy(nodeSpecs?.nodeSpecs, 'componentType'),
    (value, key: Dedicatedv1beta1ComponentType) => ({
      componentType: key,
      nodeSpecs: value
    })
  )

  return (
    <FormProvider {...formProps}>
      <ClusterPageShell title="Modify Cluster" headerProps={{ withBack: true }} bodyProps={{ pb: 96 }}>
        <Flex
          sx={{
            height: '100%',
            gap: 24,
            justifyContent: 'center'
          }}
        >
          <Box w={720}>
            <FormForTidbGroup
              loading={isLoading}
              clusterSpecs={nodeSpecByType}
              defaultNodes={defaultNodes}
              tidbGroupFullSupported={tidbGroupFullSupported}
              provider={cloudProvider}
            />
          </Box>
          <Box w={408} miw={408}>
            <SumForTidbGroup cluster={cluster} clusterSpecs={nodeSpecByType} disabled={isLoading} />
          </Box>
        </Flex>
      </ClusterPageShell>
    </FormProvider>
  )
})

export const ModifyingForTidbGroup = observer(({ clusterId }: { clusterId: string }) => {
  const {
    store: {
      lastVisitLocation: { orgId, projectId }
    }
  } = useStores()
  const clusterQuery = useClusterServiceGetCluster(
    clusterId,
    {
      orgId,
      projectId
    },
    {
      query: {
        enabled: !!(clusterId && orgId && projectId),
        select: (data) => data?.dedicatedCluster,
        refetchOnMount: false,
        refetchOnWindowFocus: false
      }
    }
  )

  if (clusterQuery.isLoading) {
    return null
  }

  if (!clusterQuery.data) {
    return null
  }

  return <ModifyingForTidbGroupInner cluster={clusterQuery.data} orgId={orgId} />
})
