import { Alert, Button, Card, Divider, Group, Loader, Modal, Progress, Stack, Text, Typography } from '@tidbcloud/uikit'
import { useMount } from 'ahooks'
import { capitalize } from 'lodash-es'
import { observer } from 'mobx-react'
import { Fragment, useEffect, useMemo, useRef, useState } from 'react'
import { useFormContext } from 'react-hook-form'

import type { PremiumDMFormData } from 'dbaas/screens/DataMigration/CreateDataMigrationPremium.types'
import { useSharedTiDBContext } from 'dbaas/screens/NextGen/tidb-mgmt-container/shared/tidb-context'
import {
  useCreatePremiumMigrationPrecheck,
  usePremiumMigrationCancelPrecheck,
  usePremiumMigrationGetPrecheck
} from 'dbaas/services/dataflow'
import {
  PremiumDMTaskImportModeENUM,
  V1beta2PrecheckItemType,
  V1beta2PremiumMigrationPrecheckStatus
} from 'dbaas/services/dataflow/interface'
import { eventTracking } from 'dbaas/utils/tracking'

import PremiumCheckItem, { PremiumCheckItemProps } from './PremiumCheckItem'
import classes from './PremiumDMStep3.module.css'

const terminalStatuses: V1beta2PremiumMigrationPrecheckStatus[] = [
  V1beta2PremiumMigrationPrecheckStatus.CANCELED,
  V1beta2PremiumMigrationPrecheckStatus.FAILED,
  V1beta2PremiumMigrationPrecheckStatus.FINISHED
]

const mapItemStatus = (status?: string): PremiumCheckItemProps['status'] => {
  switch (status) {
    case 'SUCCESS':
      return 'success'
    case 'FAILED':
      return 'fail'
    default:
      return 'warn'
  }
}

const getDisplayStatus = (status?: string) => {
  if (!status) return '-'
  return capitalize(status.toLowerCase().replaceAll('_', ' '))
}

const Step3 = ({
  onCancel,
  onGoPrev,
  onFinish
}: {
  onFinish: () => void
  onCancel: () => void
  onGoPrev: () => void
}) => {
  const tidb = useSharedTiDBContext()
  const { getValues, setValue, watch } = useFormContext<PremiumDMFormData>()
  const precheckId = watch('precheckId')
  const cancelPrecheck = usePremiumMigrationCancelPrecheck()
  const [canStopPolling, setCanStopPolling] = useState(false)
  const [modalOpen, setModalOpen] = useState(false)
  const {
    data: precheckData,
    isLoading,
    refetch
  } = usePremiumMigrationGetPrecheck(tidb.tidbId!, precheckId, {
    query: {
      enabled: Boolean(tidb.tidbId && precheckId) && !canStopPolling,
      refetchInterval: 5000,
      refetchOnWindowFocus: false
    }
  })
  const precheck = useCreatePremiumMigrationPrecheck()
  const progressColor = useMemo(() => {
    if (precheckData?.status === V1beta2PremiumMigrationPrecheckStatus.FINISHED) {
      return 'green'
    }
    if (precheckData?.status === V1beta2PremiumMigrationPrecheckStatus.FAILED) {
      return 'red'
    }
    if (precheckData?.status === V1beta2PremiumMigrationPrecheckStatus.RUNNING) {
      return 'peacock'
    }
    return 'gray'
  }, [precheckData])
  const totalCount = precheckData?.total ?? Infinity
  const successCount = precheckData?.success_cnt ?? 0
  const failCount = precheckData?.failed_cnt ?? 0
  const warnCount = precheckData?.warn_cnt ?? 0
  const completedCount = successCount + failCount + warnCount
  const percentage = Number.isFinite(totalCount) && totalCount > 0 ? Math.floor((completedCount / totalCount) * 100) : 0
  const warningItems = useMemo(
    () => precheckData?.items?.filter((i) => i.status === 'WARNING').map((i) => i.description!) ?? [],
    [precheckData]
  )
  const ignoredItemsRef = useRef<typeof warningItems>([])
  const hasImportModeWarning = precheckData?.items?.some(
    (i) => i.type === V1beta2PrecheckItemType.LIGHTNING_TABLE_EMPTY_CHECKING && i.status === 'WARNING'
  )
  const displayedCheckItems = precheckData?.items?.filter((i) => i.status !== 'SUCCESS') ?? []
  const isEssentialV2PrecheckRunning =
    tidb.computed.isEssentialV2 && precheckData?.status === V1beta2PremiumMigrationPrecheckStatus.RUNNING

  const onGoNextStep = async (shouldIgnoreWarningCheck?: boolean) => {
    if (!shouldIgnoreWarningCheck && ignoredItemsRef.current.length < warningItems.length) {
      setModalOpen(true)
      return
    }

    if (precheckData?.status === V1beta2PremiumMigrationPrecheckStatus.FINISHED) {
      if (hasImportModeWarning) {
        setValue('import_mode', PremiumDMTaskImportModeENUM.IMPORTMODE_LOGICAL)
      }
      onFinish()
      return
    }

    await precheckAgain()
  }

  const precheckAgain = async () => {
    if (isEssentialV2PrecheckRunning) {
      return
    }

    const formData = getValues()
    setModalOpen(false)

    const res = await precheck.mutateAsync({
      tidbId: tidb.tidbId!,
      data: {
        display_name: formData.name,
        sources: formData.sources,
        import_mode: formData.import_mode,
        target: {
          user: formData.cluster_username,
          password: formData.cluster_password
        },
        mode: formData.migration_mode
      }
    })

    setValue('precheckId', res.precheck_id ?? '')
  }

  const onCancelPrecheck = async () => {
    await cancelPrecheck.mutateAsync({
      tidbId: tidb.tidbId!,
      precheckId
    })

    refetch()

    eventTracking('Premium data migration job precheck canceled')
  }

  useEffect(() => {
    setCanStopPolling(false)
  }, [precheckId])

  useEffect(() => {
    if (
      (Number.isFinite(totalCount) && totalCount > 0 && completedCount >= totalCount) ||
      terminalStatuses.includes(precheckData?.status!)
    ) {
      setCanStopPolling(true)
    }
  }, [completedCount, precheckData?.status, totalCount])

  useMount(() => {
    eventTracking('Enter the step to pre check Premium data migration job')
  })

  if (isLoading) {
    return <Loader size="xs" />
  }

  return (
    <Card withBorder shadow="none" p={0} data-testid="premium-dm-step3">
      <Stack m={24}>
        <Typography variant="headline-sm">Pre-check Process</Typography>

        <div className="wd-flex wd-items-center wd-gap-8">
          <Progress color={progressColor} value={percentage} sx={{ flex: 1 }} />
          <b>{getDisplayStatus(precheckData?.status)}</b>
          <b>{percentage}%</b>
          {!terminalStatuses.includes(precheckData?.status!) && (
            <Button variant="default" onClick={onCancelPrecheck} loading={cancelPrecheck.isLoading}>
              Cancel
            </Button>
          )}
        </div>
        <p>
          Total {totalCount} items,{' '}
          <Typography span c="blue">
            {completedCount}
          </Typography>{' '}
          completed,{' '}
          <Typography span c="green">
            {successCount}
          </Typography>{' '}
          passed,{' '}
          <Typography span c="yellow">
            {warnCount}
          </Typography>{' '}
          with warning,{' '}
          <Typography span c="red">
            {failCount}
          </Typography>{' '}
          failed.
        </p>
      </Stack>

      <Divider />

      {displayedCheckItems.length > 0 && (
        <Stack m={24}>
          <Typography variant="headline-sm">Pre-check Result</Typography>

          <div>
            <Group
              gap={0}
              className={classes.resultHeader}
              sx={(theme) => ({ backgroundColor: theme.colors.carbon[2] })}
            >
              <b>Check Item</b>
              <b>Status</b>
            </Group>
            {displayedCheckItems.map((item) => (
              <Fragment key={item.description}>
                <PremiumCheckItem
                  desc={item.description}
                  reason={item.reason}
                  solution={item.solution}
                  solution_doc_url={item.solution_doc_url}
                  type={item.type}
                  status={mapItemStatus(item.status)}
                  onIgnore={(desc) => {
                    ignoredItemsRef.current.push(desc)
                  }}
                />
              </Fragment>
            ))}
          </div>
        </Stack>
      )}

      {hasImportModeWarning && (
        <Alert title="Warning" color="yellow" m={24}>
          In physical migration mode, the target tables requiring data migration must be empty. However,{' '}
          {precheckData?.items?.find((i) => i.type === V1beta2PrecheckItemType.LIGHTNING_TABLE_EMPTY_CHECKING)?.reason}.
          Please go back to exclude these tables, or the migration will be performed in logical mode.
        </Alert>
      )}

      <Group justify="flex-end" m={24}>
        <Button variant="default" type="button" onClick={onCancel}>
          Cancel
        </Button>

        <Button variant="outline" type="button" onClick={onGoPrev}>
          Previous
        </Button>

        <Button
          type="button"
          onClick={() => onGoNextStep()}
          loading={precheck.isLoading}
          disabled={isEssentialV2PrecheckRunning}
        >
          {precheckData?.status !== V1beta2PremiumMigrationPrecheckStatus.FINISHED ? 'Check Again' : 'Next'}
        </Button>
      </Group>

      <Modal
        opened={modalOpen}
        size="xl"
        centered
        title={
          <Text fw={700} fz={20}>
            Pre-check result exists warnings
          </Text>
        }
        onClose={() => setModalOpen(false)}
      >
        <Stack>
          <div>
            <p>You can:</p>
            <ul>
              <li>
                Click <b>Check Again</b> to operate according to warning details and pass all check items.
              </li>
              <li>
                Click <b>Ignore warnings</b> and go to the next step immediately. <b>Note</b> that ignoring all warnings
                may result in job failures or data inconsistencies.
              </li>
            </ul>
          </div>

          <Group justify="flex-end">
            <Button
              variant="default"
              type="button"
              loading={precheck.isLoading}
              disabled={isEssentialV2PrecheckRunning}
              onClick={precheckAgain}
            >
              Check Again
            </Button>
            <Button variant="default" type="button" onClick={() => onGoNextStep(true)}>
              Ignore warnings
            </Button>
          </Group>
        </Stack>
      </Modal>
    </Card>
  )
}

export const PremiumDMStep3 = observer(Step3)
