import { Button, Group, Stack, Typography, HoverCard, Box, Loader, TextInput } from '@tidbcloud/uikit'
import { MRT_ColumnDef, ProTable } from '@tidbcloud/uikit/biz'
import { useMediaQuery, useDebouncedCallback } from '@tidbcloud/uikit/hooks'
import { IconXCircle, IconInfoCircle, IconSearchSm, IconXClose } from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'
import { useRef, useState } from 'react'
import { useHistory, useLocation } from 'react-router-dom'

import { HeroComponent } from 'dbaas/components/Measurement'
import { TableFallback } from 'dbaas/components/Table/TableFallback'
import TimeComponent from 'dbaas/components/TimeComponent'
import { getSharedClusterFromDedicated } from 'dbaas/features/ClusterManagement/cluster'
import { DedicatedCreationAlert } from 'dbaas/features/ClusterManagement/dedicated/creation/CreationAlert'
import { getCloudProviderLabel } from 'dbaas/features/Project/profile'
import { StateTag } from 'dbaas/screens/Cluster/ClusterInfo'
import { ClusterOperations } from 'dbaas/screens/Cluster/Operations'
import { StarterListOperation } from 'dbaas/screens/ConsoleV2/features/Clusters/StarterListOperation'
import { useRequestSupport } from 'dbaas/screens/HelpCenter/RequestSupport/helper'
import { ServicePlanTag } from 'dbaas/screens/NextGen/shared/tidb-instance/service-plan/ServicePlanTag'
import { useClusterServiceListClusters } from 'dbaas/services/api-clients/v2023/cluster-management/v1beta1'
import {
  BffclusterManagementv1beta1Cluster,
  ClusterClusterType
} from 'dbaas/services/api-clients/v2023/cluster-management/v1beta1/interface'
import { Commonv1beta1ClusterState } from 'dbaas/services/api-clients/v2025/tidb-management/v1beta2/interface'
import { ResponseError } from 'dbaas/services/errorCodes'
import useStores from 'dbaas/stores/useStores'
import { eventTracking } from 'dbaas/utils/tracking'

const DEFAULT_PAGE_SIZE = 10

export const ClusterList = observer(() => {
  const {
    store: {
      tenantData: { id: orgId },
      activeProjectId: projectId
    }
  } = useStores()

  const { open: openSupport } = useRequestSupport()
  const [pagination, setPagination] = useState<{
    pageIndex: number
    pageSize: number
  }>({
    pageIndex: 0,
    pageSize: DEFAULT_PAGE_SIZE
  })
  const [params, setParams] = useState<{ name?: string }>({ name: '' })
  const firstLoadedRef = useRef(false)
  const location = useLocation<{ from?: string }>()
  const [debouncedParams, setDebouncedParams] = useState<{ name?: string }>({ name: '' })

  const handleSearch = useDebouncedCallback((value: string) => {
    setDebouncedParams((prev) => ({ ...prev, name: value }))
    setPagination((prev) => ({ ...prev, pageIndex: 0 }))
    eventTracking('Cluster Search Text Changed')
  }, 500)

  const {
    data: clusters,
    isLoading,
    error,
    refetch
  } = useClusterServiceListClusters(
    {
      orgId,
      projectId,
      name: debouncedParams.name || undefined,
      pageSize: pagination.pageSize,
      skip: pagination.pageIndex * pagination.pageSize
    },
    {
      query: {
        retry: 3,
        retryDelay: 5 * 1000,
        refetchInterval: (data) => {
          const serverlessCreating = data?.clusters?.some(
            (cluster) =>
              cluster.clusterType === ClusterClusterType.SERVERLESS &&
              (cluster.serverlessCluster?.state === Commonv1beta1ClusterState.CREATING ||
                cluster.serverlessCluster?.state === Commonv1beta1ClusterState.RESTORING)
          )

          if (serverlessCreating) {
            return 5 * 1000
          }

          return 60 * 1000
        },
        refetchOnWindowFocus: (query) => {
          if (query.state.error) {
            return false
          }
          return true
        },
        onSuccess: () => {
          if (!firstLoadedRef.current) {
            firstLoadedRef.current = true
          }
        }
      }
    }
  )

  const matchedXl = useMediaQuery('(max-width: 1500px)')
  const history = useHistory()

  const clusterColumns: MRT_ColumnDef<BffclusterManagementv1beta1Cluster>[] = [
    {
      header: 'Cluster Name',
      Header: () => {
        return <Typography pl={16}>Cluster Name</Typography>
      },
      Cell: ({ row: rowData }) => {
        const row = rowData.original
        const unavailable =
          row.clusterType === ClusterClusterType.DEDICATED &&
          (row.dedicatedCluster?.state === Commonv1beta1ClusterState.CREATING ||
            row.dedicatedCluster?.state === Commonv1beta1ClusterState.RESTORING)

        return (
          <Typography
            tabIndex={0}
            variant="label-lg"
            c={unavailable ? 'carbon.6' : 'peacock.7'}
            ml={16}
            sx={{
              cursor: unavailable ? 'not-allowed' : 'pointer',
              maxWidth: matchedXl ? 300 : 500,
              overflow: 'hidden',
              wordBreak: 'keep-all',
              whiteSpace: 'nowrap',
              textOverflow: 'ellipsis'
            }}
            onClick={() => {
              if (unavailable) {
                return
              }
              eventTracking('To Cluster Detail Link Clicked', {
                'Cluster Type': row.clusterType === ClusterClusterType.SERVERLESS ? 'Serverless' : 'Dedicated',
                from: 'list v3'
              })
              history.push(`/clusters/${row.serverlessCluster?.clusterId || row.dedicatedCluster?.clusterId}/overview`)
            }}
          >
            {row.serverlessCluster?.displayName || row.dedicatedCluster?.displayName}
          </Typography>
        )
      }
    },
    {
      header: 'Status',
      accessorFn: (row) => {
        const serverless = row.serverlessCluster
        const dedicated = row.dedicatedCluster
        const isDedicatedInsufficient = dedicated?.annotations?.['tidb.cloud/insufficient-vm-resource'] === 'true'

        return (
          <Group>
            <StateTag displayStatus={serverless?.state || dedicated?.state} />
            {isDedicatedInsufficient && (
              <HoverCard>
                <HoverCard.Dropdown>
                  <Typography>{`No sufficient resource is available on cloud provider now`}</Typography>
                </HoverCard.Dropdown>
                <HoverCard.Target>
                  <IconInfoCircle size={14} strokeWidth="2" c="yellow" cursor="pointer" />
                </HoverCard.Target>
              </HoverCard>
            )}
          </Group>
        )
      }
    },
    {
      header: 'Plan',
      accessorFn: (row) => {
        return (
          <ServicePlanTag
            servicePlan={
              row.clusterType === ClusterClusterType.SERVERLESS
                ? (row.serverlessCluster?.servicePlan ?? 'Starter')
                : 'Dedicated'
            }
          />
        )
      }
    },
    {
      header: 'Cloud',
      accessorFn: (row) => {
        return getCloudProviderLabel(row.serverlessCluster?.region.provider || row.dedicatedCluster?.cloudProvider)
      },
      size: 110
    },
    {
      header: 'Region',
      accessorFn: (row) => {
        return row.serverlessCluster?.region.displayName || row.dedicatedCluster?.regionDisplayName
      }
    },
    {
      header: 'Version',
      accessorFn: (row) => row.serverlessCluster?.version || row.dedicatedCluster?.version,
      size: 100
    },
    {
      header: 'Creation Time',
      accessorFn: (row) => {
        return (
          <TimeComponent
            time={row.serverlessCluster?.createTime || row.dedicatedCluster?.createTime || ''}
            format="YYYY-MM-DD HH:mm:ss"
          ></TimeComponent>
        )
      }
    },
    {
      header: 'Action',
      accessorFn: (row) => {
        const isDedicated = row.clusterType === ClusterClusterType.DEDICATED

        if (isDedicated) {
          const cluster = getSharedClusterFromDedicated(row.dedicatedCluster)

          return <ClusterOperations cluster={cluster} position="bottom-end" actionVariant="subtle" from="list" />
        }

        return <StarterListOperation cluster={row.serverlessCluster!} />
      },
      size: 80
    }
  ]

  // case 1: access denied
  if (error?.code === 403 || (error instanceof ResponseError && error?.errorCode === 403)) {
    return (
      <Typography variant="body-lg" ml={24}>
        You don't belong to this project. Please ask Organization Owner or Project Owner to add you into this project.
      </Typography>
    )
  }

  // case 2: first load failed
  if (error && !firstLoadedRef.current) {
    return (
      <Stack align="center">
        <IconXCircle size={48} color="red" />
        <Typography variant="headline-lg" c="carbon.7">
          Fetch failed.
        </Typography>
        <Typography variant="body-lg" c="carbon.7">
          Please retry in a short while or contact <a onClick={() => openSupport()}>technical support</a>.
        </Typography>
        <Button
          onClick={() => {
            refetch()
          }}
        >
          Retry
        </Button>
      </Stack>
    )
  }

  if (!firstLoadedRef.current) {
    return (
      <Box sx={{ display: 'flex', justifyContent: 'center' }} mt={48} data-testid="loader">
        <Loader />
      </Box>
    )
  }

  const fromDedicatedClusterCreation = location.state?.from === 'dedicated-cluster-creation'

  return (
    <>
      <HeroComponent />
      {fromDedicatedClusterCreation && (
        <DedicatedCreationAlert
          onClose={() => {
            history.replace('/project/clusters')
          }}
        />
      )}
      <Group px={24} mb={24}>
        <TextInput
          w={240}
          name="name"
          placeholder="Search Cluster"
          value={params.name}
          onChange={(event) => {
            setParams({ ...params, name: event.target.value })
            handleSearch(event.target.value)
          }}
          leftSection={<IconSearchSm size={14} sx={{ cursor: 'pointer' }} />}
          rightSection={
            !!params.name && (
              <IconXClose
                size={14}
                sx={{ cursor: 'pointer' }}
                onClick={() => {
                  setParams({ ...params, name: '' })
                  handleSearch('')
                  eventTracking('Cluster Search Text Cleared')
                }}
              />
            )
          }
        />
      </Group>
      <ProTable
        loading={isLoading}
        columns={clusterColumns}
        data={clusters?.clusters || []}
        manualPagination={true}
        enablePagination={true}
        state={{ pagination }}
        rowCount={clusters?.totalSize || 0}
        renderEmptyRowsFallback={() => {
          return (
            <TableFallback height="calc(100vh - 280px)">
              <TableFallback.Empty
                title={debouncedParams.name ? 'No clusters found' : 'Get started by creating a cluster'}
                desc=""
              />
            </TableFallback>
          )
        }}
        onPaginationChange={setPagination}
        mantinePaperProps={{ mx: 24 }}
      />
    </>
  )
})

export default ClusterList
