import { Alert, Button, Code, Group, Modal, notifier, Skeleton, Stack, Typography } from '@tidbcloud/uikit'
import { Form, FormTextInput } from '@tidbcloud/uikit/biz'
import { useToggle } from '@tidbcloud/uikit/hooks'
import { groupBy } from 'lodash-es'
import { observer } from 'mobx-react'
import { useForm } from 'react-hook-form'
import { Link } from 'react-router-dom'

import { ModalCodeTitle } from 'dbaas/components'
import { SharedCluster } from 'dbaas/features/ClusterManagement/cluster'
import { useDeleteCluster } from 'dbaas/services/api-clients/legacy/central'
import { Status as GooglerpcStatus } from 'dbaas/services/api-clients/legacy/serverless/interface'
import { useListBackups, useQueryBackupSettingV2 } from 'dbaas/services/dataflow'
import { DataflowBackupType } from 'dbaas/services/dataflow/interface'
import useStores from 'dbaas/stores/useStores'

interface DedicatedDeletionModalBodyProps {
  onClose: () => void
  mutator: ReturnType<typeof useDeleteCluster<GooglerpcStatus>>
  cluster: Pick<SharedCluster, 'id' | 'displayName'>
}

const DedicatedDeletionModalBody = observer(({ cluster, mutator, onClose }: DedicatedDeletionModalBodyProps) => {
  const {
    store: {
      lastVisitLocation: { orgId, projectId },
      tenantData: { name: orgName },
      activeProject: { name: projectName }
    }
  } = useStores()
  const { id: clusterId, displayName: clusterName } = cluster
  const [stage, toggleStage] = useToggle(['first', 'second'] as const)

  const backupCountQuery = useListBackups(
    orgId,
    projectId,
    clusterId,
    { per_page: 999, page: 1 },
    {
      query: {
        refetchOnWindowFocus: false,
        select: (data) => {
          const backupGroups = groupBy(data?.items, 'type')
          const autoCount = backupGroups?.[DataflowBackupType.AUTO]?.length ?? 0
          const manualCount = backupGroups?.[DataflowBackupType.MANUAL]?.length ?? 0
          const existed = !!autoCount || !!manualCount
          const single = existed && (!autoCount || !manualCount)
          const countGroups = [
            {
              label: 'automatic',
              count: autoCount
            },
            {
              label: 'manual',
              count: manualCount
            }
          ]

          return {
            existed,
            single,
            tree: {
              auto: autoCount,
              manual: manualCount
            },
            groups: countGroups
          }
        }
      }
    }
  )
  const backupCountDescs = backupCountQuery.data?.groups
    ?.filter((el) => el.count)
    ?.map((el) => `${el.count} ${el.label}`)
  const backupRetentionQuery = useQueryBackupSettingV2(orgId, projectId, clusterId, {
    query: {
      refetchOnWindowFocus: false,
      select: (data) => data?.snapshot_backup_schedule?.retention_policy?.retention_period
    }
  })

  const onSubmit = () => {
    return mutator.mutateAsync({
      orgId,
      projectId,
      clusterId
    })
  }
  const form = useForm<{ inputClusterName: string }>({
    mode: 'onChange',
    defaultValues: {
      inputClusterName: ''
    }
  })
  const { watch } = form
  const inputClusterName = watch('inputClusterName')
  const confirmationName = `${orgName}/${projectName}/${clusterName}`.trim()
  const isConfirmationMatched = inputClusterName === confirmationName

  if (backupCountQuery.isFetching || backupRetentionQuery.isFetching) {
    return (
      <>
        <Stack mb="xl">
          <Skeleton height={20} radius="sm" />
          <Skeleton height={20} radius="sm" />
          <Skeleton height={20} radius="sm" />
          <Skeleton height={20} radius="sm" />
        </Stack>
        <Group justify="flex-end">
          <Skeleton width={96} height={40} />
          <Skeleton width={96} height={40} />
        </Group>
      </>
    )
  }

  if (backupCountQuery.data?.existed && stage === 'first') {
    return (
      <>
        <Stack mb="xl">
          <Typography variant="body-lg">
            Your cluster has{' '}
            {backupCountDescs?.map((text, index, arr) => (
              <>
                <b>{text}</b>
                {arr.length > 1 && !index && ' and '}
              </>
            ))}{' '}
            backups.
          </Typography>
          <Typography variant="body-lg">
            You can find and restore them in the "Project Settings {'> '}
            <Link to="/project/recycle-bin">Recycle Bin</Link>" after deletion.
          </Typography>
          <Typography variant="body-lg">
            Automatic backups will expire and be automatically deleted after {backupRetentionQuery.data || 0} days
            except the latest one. The latest one will not be deleted unless you explicitly delete it.
          </Typography>
          <Typography variant="body-lg">
            Manual backups will be kept in the Recycle Bin until manually deleted.
          </Typography>
          <Alert color="yellow">Please be aware that backups will continue to incur charges until deleted.</Alert>
        </Stack>
        <Group justify="flex-end">
          <Button variant="default" onClick={onClose} data-mp-event="Cancel Delete Modal Button Clicked">
            Cancel
          </Button>
          <Button
            onClick={() => toggleStage('second')}
            data-mp-event="Continue Delete Dedicated Cluster Button Clicked"
          >
            Continue
          </Button>
        </Group>
      </>
    )
  }

  if (!backupCountQuery.data?.existed || stage === 'second') {
    return (
      <Stack>
        {!backupCountQuery.data?.existed && <Typography variant="body-lg">Your cluster has no backups.</Typography>}
        <Typography variant="body-lg">
          To confirm, type{' '}
          <Code fz={13} fw={600} bg="carbon.3" c="carbon.9" sx={{ whiteSpace: 'pre-wrap' }}>
            {confirmationName}
          </Code>{' '}
          in the box below.
        </Typography>
        <Form
          layout="none"
          form={form}
          onSubmit={onSubmit}
          onCancel={onClose}
          actionsProps={{
            confirmText: 'I understand, delete it',
            confirmProps: {
              color: 'red',
              variant: 'light',
              disabled: !isConfirmationMatched,
              'data-mp-event': 'Deleted A Cluster'
            },
            cancelProps: {
              disabled: mutator.isLoading,
              'data-mp-event': 'Cancel Delete Modal Button Clicked'
            }
          }}
        >
          <FormTextInput
            name="inputClusterName"
            autoFocus
            rules={{
              required: 'Required',
              validate: (value) => value === confirmationName || 'Incorrect cluster name'
            }}
          />
        </Form>
      </Stack>
    )
  }

  return null
})

interface DedicatedDeletionModalProps {
  cluster: Pick<SharedCluster, 'id' | 'displayName'>
  opened: boolean
  onClose: () => void
  onFinish: () => Promise<unknown>
}

export const DedicatedDeletionModal = ({ cluster, opened, onClose, onFinish }: DedicatedDeletionModalProps) => {
  const mutator = useDeleteCluster({
    mutation: {
      onSuccess: async () => {
        await onFinish?.()
        onClose()
        notifier.success('The cluster is successfully deleted.')
      }
    }
  })
  const closable = !mutator.isLoading

  return (
    <Modal
      size="xl"
      centered
      trapFocus={false}
      opened={opened}
      onClose={onClose}
      closeOnClickOutside={closable}
      closeOnEscape={closable}
      withCloseButton={closable}
      title={
        <>
          Delete <ModalCodeTitle maxWidth={400}>{cluster.displayName}</ModalCodeTitle> Cluster
        </>
      }
    >
      <DedicatedDeletionModalBody cluster={cluster} mutator={mutator} onClose={onClose} />
    </Modal>
  )
}
