import {
  Alert,
  Badge,
  Box,
  Button,
  Card,
  Center,
  Group,
  HoverCard,
  Loader,
  notifier,
  Stack,
  Tooltip,
  Typography
} from '@tidbcloud/uikit'
import { IconAlertCircle } from '@tidbcloud/uikit/icons'
import { capitalize } from 'lodash-es'
import { observer } from 'mobx-react'
import { useMemo } from 'react'
import { useHistory } from 'react-router-dom'

import { AccessDeniedHoverHint } from 'dbaas/contexts/access-control'
import { SharedCluster } from 'dbaas/features/ClusterManagement/cluster'
import { useSqlEditorStatus } from 'dbaas/features/ClusterManagement/feats/chat2query/status'
import { canCancelImport, canCancelServerlessImport } from 'dbaas/features/Import'
import { useImportServiceCancelImport, useImportServiceGetImport } from 'dbaas/services/api-clients/legacy/serverless'
import { ImportStateEnum } from 'dbaas/services/api-clients/legacy/serverless/interface'
import { exitImport, useCancelImport, useGetImport } from 'dbaas/services/dataflow'
import {
  DataflowImportGetRespStatus,
  DataflowImportTableCompletionInfo,
  DataflowImportTableCompletionInfoResult
} from 'dbaas/services/dataflow/interface'
import { getErrorMessage } from 'dbaas/services/errorCodes'
import useStores from 'dbaas/stores/useStores'

import { ImportProgressContent } from '../ImportTaskDetail/ImportProgress'
import { ImportSummaryList } from '../ImportTaskDetail/Summary'

const TableDetail = ({ message, table_name, result }: DataflowImportTableCompletionInfo) => {
  const [db, table] = table_name.replaceAll('`', '').split('.')
  const badgeColor = useMemo(() => {
    if (result === DataflowImportTableCompletionInfoResult.SUCCESS) return 'green'
    if (result === DataflowImportTableCompletionInfoResult.ERROR) return 'red'
    if (result === DataflowImportTableCompletionInfoResult.WARNING) return 'yellow'
    return 'gray'
  }, [result])
  const hasErrorMessage = result === DataflowImportTableCompletionInfoResult.ERROR && !!message

  return (
    <Box>
      <Group grow px={16} py={12} wrap="nowrap">
        <Typography variant="label-lg" truncate lh="26px">
          {db}
        </Typography>
        <Typography variant="label-lg" truncate lh="26px">
          {table}
        </Typography>

        <HoverCard withArrow position="top-start" shadow="md" disabled={!message} zIndex={10000}>
          <HoverCard.Target>
            <Box sx={{ cursor: message ? 'pointer' : 'default' }}>
              <Badge variant="dot" size="lg" p={0} color={badgeColor}>
                {capitalize(result)}
              </Badge>
            </Box>
          </HoverCard.Target>

          <HoverCard.Dropdown>
            <Typography variant="body-md" maw={150} sx={{ wordBreak: 'break-all' }}>
              {message}
            </Typography>
          </HoverCard.Dropdown>
        </HoverCard>
      </Group>

      {hasErrorMessage && (
        <Alert color="red" icon={<IconAlertCircle size={16} />}>
          <Typography variant="body-md">{message}</Typography>
        </Alert>
      )}
    </Box>
  )
}

export const ImportTaskDetailDrawer = observer(
  ({ id, cluster, onCancel }: { id: string; cluster: SharedCluster; onCancel?: () => void; open?: boolean }) => {
    const {
      store: { activeProjectId, tenantData, currentCluster },
      actions
    } = useStores()
    const isServerless = cluster?.computed.isServerless
    const importActionAccessCheckProps = cluster?.computed.isServerless
      ? {
          id: 'TidbxImportAction' as const,
          scopeProps: { tidbId: cluster.id }
        }
      : {
          id: 'ClusterImportAction' as const
        }
    const sqlEditorState = useSqlEditorStatus(cluster)
    const history = useHistory()

    const isCompleted = (status?: DataflowImportGetRespStatus | ImportStateEnum) => {
      if (!status) return false
      return (
        [
          DataflowImportGetRespStatus.COMPLETED,
          DataflowImportGetRespStatus.CANCELED,
          DataflowImportGetRespStatus.FAILED,
          ImportStateEnum.COMPLETED,
          ImportStateEnum.CANCELED,
          ImportStateEnum.FAILED
        ] as (DataflowImportGetRespStatus | ImportStateEnum)[]
      ).includes(status)
    }

    const {
      data: dedicatedImportData,
      refetch,
      isLoading: isLoadingDedicatedImport
    } = useGetImport(tenantData.id, activeProjectId, currentCluster?.id!, id, {
      query: {
        enabled: !isServerless && !!id,
        refetchInterval: (data) => {
          if (isCompleted(data?.status)) {
            return false
          }
          return 1000
        },
        async onSuccess(data) {
          if (isCompleted(data?.status)) {
            await exitImport(tenantData.id, activeProjectId, currentCluster?.id!, id!)
            actions.fetchCluster(currentCluster?.id!) // fetch latest cluster status
          }
        }
      }
    })

    const { data: serverlessImportData, isLoading: isServerlessImportLoading } = useImportServiceGetImport(
      tenantData.id,
      activeProjectId,
      currentCluster?.id!,
      id,
      {
        query: {
          enabled: isServerless && !!id,
          refetchInterval: (data) => {
            if (isCompleted(data?.state)) {
              return false
            }
            return 3000
          }
        }
      }
    )

    const canCancel = isServerless
      ? canCancelServerlessImport(serverlessImportData?.state!)
      : canCancelImport(dedicatedImportData?.status!)
    const cancelImport = useCancelImport()
    const cancelServerlessImport = useImportServiceCancelImport()
    const canQueryData = isServerless
      ? serverlessImportData?.state === ImportStateEnum.COMPLETED && serverlessImportData?.complete_percent === 100
      : dedicatedImportData?.completed_percent === 100 &&
        dedicatedImportData.status === DataflowImportGetRespStatus.COMPLETED
    const targetDatabase = isServerless
      ? serverlessImportData?.creation_details?.source?.local?.target_database
      : dedicatedImportData?.import_create_req?.local_import_cfg?.target_table?.schema
    const targetTable = isServerless
      ? serverlessImportData?.creation_details?.source?.local?.target_table
      : dedicatedImportData?.import_create_req?.local_import_cfg?.target_table?.table
    const handleCancel = async () => {
      try {
        if (isServerless) {
          await cancelServerlessImport.mutateAsync({
            orgId: tenantData.id,
            projectId: activeProjectId,
            clusterId: currentCluster?.id!,
            id,
            data: {
              reason: 'user_cancel'
            }
          })
        } else {
          await cancelImport.mutateAsync({
            orgId: tenantData.id,
            projectId: activeProjectId,
            clusterId: currentCluster?.id!,
            id
          })
        }
        onCancel?.()
        refetch()
      } catch (e) {
        notifier.error(getErrorMessage(e, true))
      }
    }
    const handleQueryData = () => {
      actions.setPreloadedSQLEditor({
        name: `import-task-${serverlessImportData?.id}`,
        db: targetDatabase,
        table: targetTable
      })
      history.push(`/clusters/${currentCluster?.id}/sqleditor`)
    }

    const finished = isServerless ? isCompleted(serverlessImportData?.state) : isCompleted(dedicatedImportData?.status)
    const data = isServerless ? serverlessImportData : dedicatedImportData

    if (isLoadingDedicatedImport || isServerlessImportLoading) {
      return (
        <Center>
          <Loader size="xs" m="auto" />
        </Center>
      )
    }

    if (!id || (!dedicatedImportData && !serverlessImportData)) {
      return <Center>Not found</Center>
    }

    return (
      <Stack h="100%" justify="space-between" gap={0} px={8} className="import-task-detail-drawer">
        <Stack style={{ maxHeight: 'calc(100vh - 148px)', flexGrow: 1, overflow: 'auto' }}>
          <ImportSummaryList data={data!} timezone={tenantData.timezone} />

          {!finished && (
            <>
              <Typography variant="headline-sm">Progress</Typography>
              <ImportProgressContent data={data!} />
            </>
          )}

          {finished && (data?.all_completed_tables?.length ?? 0) > 0 && (
            <>
              <Typography variant="headline-sm">Table Detail</Typography>

              <Card>
                <Card.Section bg="carbon.2" p={16}>
                  <Group justify="space-evenly">
                    <Typography sx={{ flex: 1 }}>Database</Typography>
                    <Typography sx={{ flex: 1 }}>Table</Typography>
                    <Typography sx={{ flex: 1 }}>Result</Typography>
                  </Group>
                </Card.Section>
                <Card.Section mah={400} sx={{ overflowY: 'auto' }}>
                  {data?.all_completed_tables?.map((i) => (
                    <TableDetail
                      table_name={i.table_name!}
                      result={i.result! as any}
                      message={i.message}
                      key={i.table_name!}
                    />
                  ))}
                </Card.Section>
              </Card>
            </>
          )}
        </Stack>

        <Group justify="flex-end">
          {canCancel && (
            <AccessDeniedHoverHint {...importActionAccessCheckProps}>
              {({ accessible }) => (
                <Button
                  variant="default"
                  loading={cancelImport.isLoading}
                  disabled={!accessible}
                  onClick={handleCancel}
                  data-mp-event="mp-canceltask-1691461015085"
                >
                  Cancel
                </Button>
              )}
            </AccessDeniedHoverHint>
          )}
          {isServerless && sqlEditorState.visible && (
            <Tooltip label="Try after the task is finished" disabled={canQueryData}>
              <div>
                <Button
                  onClick={handleQueryData}
                  disabled={!canQueryData}
                  data-mp-event="Click Explore your data by Chat2Query"
                >
                  Explore your data by SQL Editor
                </Button>
              </div>
            </Tooltip>
          )}
        </Group>
      </Stack>
    )
  }
)
