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 { DmImportMode } from 'dbaas/features/DataMigration'
import type { FormData } from 'dbaas/screens/DataMigration/CreateDataMigrationDedicated'
import { useCancelDMPrecheck, useGetPrecheck, usePrecheckJob } from 'dbaas/services/dataflow'
import { DmPrecheckItemType } from 'dbaas/services/dataflow/interface'
import useStores from 'dbaas/stores/useStores'
import { eventTracking } from 'dbaas/utils/tracking'

import CheckItem, { CheckItemProps } from './CheckItem'
import classes from './Step3.module.css'

const Step3 = ({
  onCancel,
  onGoPrev,
  onFinish,
  formData
}: {
  formData: FormData
  onFinish: (data?: any, next?: boolean) => void
  onCancel: () => void
  onGoPrev: () => void
}) => {
  const {
    store: { tenantData, activeProjectId, currentCluster }
  } = useStores()
  const { precheckId } = formData
  const cancelPrecheck = useCancelDMPrecheck()
  const [canStopPolling, setCanStopPolling] = useState(false)
  const [modalOpen, setModalOpen] = useState(false)
  const {
    data: precheckData,
    isLoading,
    refetch
  } = useGetPrecheck(tenantData.id, activeProjectId, currentCluster?.id!, precheckId, {
    query: {
      enabled: Boolean(precheckId) && !canStopPolling,
      refetchInterval: 5000
    }
  })
  const precheck = usePrecheckJob()
  const progressColor = useMemo(() => {
    if (precheckData?.status === 'finished') {
      return 'green'
    }
    if (precheckData?.status === 'failed') {
      return 'red'
    }
    if (precheckData?.status === '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 = Math.floor((completedCount / totalCount) * 100)
  const warningItems = useMemo(
    () => precheckData?.items?.filter((i) => i.status === 'warn').map((i) => i.desc!) ?? [],
    [precheckData]
  )
  const ignoredItemsRef = useRef<typeof warningItems>([])
  const hasImportModeWarning = precheckData?.items?.some(
    (i) => i.type === DmPrecheckItemType.LightningTableEmptyChecking && i.status === 'warn'
  )
  const displayedCheckItems = precheckData?.items?.filter((i) => i.status !== 'success') ?? []

  if (percentage === 100 && !canStopPolling) {
    setCanStopPolling(true)
  }

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

    if (precheckData?.status === 'finished') {
      onFinish(hasImportModeWarning ? { import_mode: DmImportMode.Logical } : undefined)
      return
    }

    await precheckAgain()
  }

  const precheckAgain = async () => {
    setModalOpen(false)

    const res = await precheck.mutateAsync({
      orgId: tenantData.id,
      projectId: activeProjectId,
      clusterId: currentCluster?.id!,
      data: {
        name: formData.name,
        sources: formData.sources,
        cluster_user: formData.cluster_username,
        cluster_password: formData.cluster_password,
        mode: formData.mode,
        full_instance_migrate: formData.full_instance_migrate,
        import_mode: formData.import_mode!
      }
    })

    onFinish({ precheckId: res.id }, false)
    refetch()
  }

  const onCancelPrecheck = async () => {
    await cancelPrecheck.mutateAsync({
      orgId: tenantData.id,
      projectId: activeProjectId,
      clusterId: currentCluster?.id!,
      id: precheckId
    })

    refetch()

    eventTracking('DataMigration job‘s precheck canceled')
  }

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

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

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

  return (
    <Card withBorder shadow="none" p={0}>
      <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>{capitalize(precheckData?.status)}</b>
          <b>{percentage}%</b>
          {!['canceled', 'finished', 'failed'].includes(precheckData?.status!) && (
            <Button
              variant="default"
              onClick={onCancelPrecheck}
              loading={cancelPrecheck.isLoading}
              data-mp-event="mp-cancel-1691461016921"
            >
              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((i) => (
              <Fragment key={i.desc}>
                <CheckItem
                  {...i}
                  status={i.status! as CheckItemProps['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 === DmPrecheckItemType.LightningTableEmptyChecking)?.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} data-mp-event="mp-cancel-1691461016922">
          Cancel
        </Button>

        <Button variant="outline" type="button" onClick={onGoPrev} data-mp-event="mp-previous-1691461016924">
          Previous
        </Button>

        <Button
          type="button"
          onClick={() => onGoNextStep()}
          loading={precheck.isLoading}
          data-mp-event="mp--1691461016926"
        >
          {precheckData?.status !== '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}
              onClick={precheckAgain}
              data-mp-event="mp-checkagain-1691461016928"
            >
              Check Again
            </Button>
            <Button
              variant="default"
              type="button"
              onClick={() => onGoNextStep(true)}
              data-mp-event="mp-ignorewarnings-1691461016930"
            >
              Ignore warnings
            </Button>
          </Group>
        </Stack>
      </Modal>
    </Card>
  )
}

export const DedicatedDMStep3 = observer(Step3)
