import { ActionIcon, Button, Center, Flex, Group, Menu, Select, Stack, TextInput, Typography } from '@tidbcloud/uikit'
import { MRT_ColumnDef, ProMultiSelect, ProTable } from '@tidbcloud/uikit/biz'
import { useDebouncedValue, useMediaQuery } from '@tidbcloud/uikit/hooks'
import { IconDotsHorizontal, IconSearchSm, IconXCircle, IconXClose } from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'
import { useMemo, useRef, useState } from 'react'
import { useHistory } from 'react-router-dom'

import { ReasonHoverHint } from 'dbaas/components/HoverHint/ReasonHoverHint'
import TimeComponent from 'dbaas/components/TimeComponent'
import { AccessDeniedHoverHint } from 'dbaas/contexts/access-control'
import { DEFAULT_HINT_CONTENT } from 'dbaas/contexts/access-control/ui/use-access-denied-hint-reason'
import { getCloudProviderLabel } from 'dbaas/features/Project'
import { PageShell } from 'dbaas/layouts/v5/page'
import { StateTag } from 'dbaas/screens/Cluster/ClusterInfo'
import { TableFallback } from 'dbaas/screens/ClusterV2/components/PausedStatus'
import { useRequestSupport } from 'dbaas/screens/HelpCenter/RequestSupport/helper'
import { useCreateResourceAccess } from 'dbaas/screens/NextGen/shared/access/use-create-resource-access'
import { ServicePlanTag } from 'dbaas/screens/NextGen/shared/tidb-instance/service-plan/ServicePlanTag'
import {
  useRegionServiceListRegions,
  useTidbServiceListTidbs
} from 'dbaas/services/api-clients/v2025/tidb-management/v1beta2'
import {
  TidbCloudOpenApinextgenv1beta2Tidb,
  TidbServiceListTidbsServicePlan,
  V1beta1RegionCloudProvider
} from 'dbaas/services/api-clients/v2025/tidb-management/v1beta2/interface'
import useStores from 'dbaas/stores/useStores'
import { MixpanelEvents } from 'dbaas/utils/tracking'

import { PremiumListOperation } from './ListOperation'

const DEFAULT_PAGE_SIZE = 10

export const TidbList = observer(() => {
  const history = useHistory()
  const {
    store: { tenantData, lastVisitLocation }
  } = useStores()
  const [params, setParams] = useState<{
    search?: string
    servicePlan?: TidbServiceListTidbsServicePlan
    regionIds?: string[]
  }>({
    search: '',
    regionIds: []
  })
  const [pagination, setPagination] = useState<{
    pageIndex: number
    pageSize: number
  }>({
    pageIndex: 0,
    pageSize: DEFAULT_PAGE_SIZE
  })
  const [debouncedParams] = useDebouncedValue(params, 300)

  const firstLoadedRef = useRef(false)
  const createResourceAccess = useCreateResourceAccess()

  const { open: openSupport } = useRequestSupport()
  const hasSearch = debouncedParams.search || debouncedParams.servicePlan || debouncedParams.regionIds?.length

  const { data, isLoading, isError, refetch } = useTidbServiceListTidbs(
    {
      orgId: tenantData.id,
      projectId: lastVisitLocation.projectId,
      pageSize: pagination.pageSize,
      skip: pagination.pageIndex * pagination.pageSize,
      servicePlan: debouncedParams.servicePlan,
      name: debouncedParams.search,
      regionIds: debouncedParams.regionIds
    },
    {
      query: {
        retry: 3,
        retryDelay: 5 * 1000,
        refetchOnWindowFocus: (query) => {
          if (query.state.error) {
            return false
          }
          return true
        },
        onSuccess: () => {
          if (!firstLoadedRef.current) {
            firstLoadedRef.current = true
          }
        },
        refetchInterval: (data) => {
          const tidbs = data?.tidbs
          const creatingTidbs = tidbs?.filter((tidb) => tidb.state === 'CREATING' || tidb.state === 'RESTORING')
          const isCreatingStarter = creatingTidbs?.some(
            (tidb) => tidb.servicePlan === TidbServiceListTidbsServicePlan.Starter
          )
          const isCreatingEssential = creatingTidbs?.some(
            (tidb) => tidb.servicePlan === TidbServiceListTidbsServicePlan.Essential
          )
          const isCreatingPremium = creatingTidbs?.some(
            (tidb) => tidb.servicePlan === TidbServiceListTidbsServicePlan.Premium
          )
          const isModifying = tidbs?.some((tidb) => tidb.state === 'MODIFYING')

          if (isModifying) {
            return 5 * 1000
          } else if (isCreatingStarter) {
            return 5 * 1000
          } else if (isCreatingEssential) {
            return 10 * 1000
          } else if (isCreatingPremium) {
            return 60 * 1000
          }

          return 10 * 60 * 1000
        }
      }
    }
  )

  const { data: regionData } = useRegionServiceListRegions(
    {
      orgId: tenantData.id,
      projectId: lastVisitLocation.projectId,
      pageSize: 100
    },
    {
      query: {
        retry: 3,
        retryDelay: 5 * 1000
      }
    }
  )

  const regionOptions = useMemo(() => {
    if (!regionData?.regions) {
      return []
    }

    const groupedRegions = regionData.regions.reduce(
      (acc, region) => {
        const provider = region.cloudProvider || region.regionId?.split('-')?.[0]
        if (!provider || !V1beta1RegionCloudProvider[provider]) {
          return acc
        }

        acc[provider] = [
          ...(acc[provider] || []),
          {
            value: region.regionId || '',
            label: region.displayName || ''
          }
        ]

        return acc
      },
      {} as Record<V1beta1RegionCloudProvider, { value: string; label: string }[]>
    )

    return Object.entries(groupedRegions).map(([provider, items]) => ({
      group: getCloudProviderLabel(provider),
      items
    }))
  }, [regionData])

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

  const clusterColumns: MRT_ColumnDef<TidbCloudOpenApinextgenv1beta2Tidb>[] = [
    {
      header: 'Name',
      Header: () => {
        return <Typography pl={16}>Name</Typography>
      },
      Cell: ({ row: rowData }) => {
        const row = rowData.original
        return (
          <Typography
            tabIndex={0}
            variant="label-lg"
            c={'peacock.7'}
            ml={16}
            sx={{
              cursor: 'pointer',
              maxWidth: matchedXl ? 300 : 500,
              overflow: 'hidden',
              wordBreak: 'keep-all',
              whiteSpace: 'nowrap',
              textOverflow: 'ellipsis'
            }}
            onClick={() => {
              history.push(`/tidbs/${row.tidbId}/overview`)
            }}
          >
            {row.displayName}
          </Typography>
        )
      }
    },
    {
      header: 'Status',
      accessorFn: (row) => {
        return (
          <Group>
            <StateTag displayStatus={row.state} />
          </Group>
        )
      }
    },
    {
      header: 'Plan',
      accessorFn: (row) => {
        return <ServicePlanTag servicePlan={row.servicePlan} />
      }
    },
    {
      header: 'Cloud',
      accessorFn: (row) => {
        return getCloudProviderLabel(row.cloudProvider)
      },
      size: 110
    },
    {
      header: 'Region',
      accessorFn: (row) => {
        return row.regionDisplayName
      }
    },
    {
      header: 'Creation Time',
      accessorFn: (row) => {
        return <TimeComponent time={row.createTime || ''} format="YYYY-MM-DD HH:mm:ss"></TimeComponent>
      }
    },
    {
      id: 'Action',
      header: '',
      accessorFn: (row) => {
        return <PremiumListOperation tidb={row} />
      },
      size: 80
    }
  ]

  return (
    <PageShell
      bodyProps={{ pb: 60 }}
      title="TiDB Instances"
      headerProps={{
        sticky: true,
        rightSection: (
          <Group gap={8}>
            <ReasonHoverHint reasons={[{ when: !createResourceAccess, content: DEFAULT_HINT_CONTENT }]}>
              {({ matched }) => (
                <Button
                  size="sm"
                  disabled={matched}
                  onClick={() => {
                    history.push('/tidbs/new')
                  }}
                  data-testid="tidb-create-link"
                  data-mp-event={MixpanelEvents.TidbResource.Create.EnterClicked}
                >
                  Create Instance
                </Button>
              )}
            </ReasonHoverHint>
            <AccessDeniedHoverHint id="TidbxRecycleBinView" scopeProps={{ projectId: lastVisitLocation.projectId }}>
              {({ accessible }) => (
                <Button
                  size="sm"
                  variant="default"
                  disabled={!accessible}
                  onClick={() => {
                    const recycleBinPlan =
                      params.servicePlan === TidbServiceListTidbsServicePlan.BYOC ? 'BYOC' : 'Premium'

                    history.push(`/tidbs/recycle-bin?plan=${recycleBinPlan}`)
                  }}
                  data-testid="recycle-bin-link"
                  data-mp-event={MixpanelEvents.RecycleBin.View.ButtonClicked}
                >
                  Recycle Bin
                </Button>
              )}
            </AccessDeniedHoverHint>
            <Menu withArrow position="bottom-end">
              <Menu.Target>
                <ActionIcon variant="default" size={32} aria-label="More actions">
                  <IconDotsHorizontal />
                </ActionIcon>
              </Menu.Target>
              <Menu.Dropdown>
                <Menu.Item
                  disabled={!createResourceAccess}
                  onClick={() => {
                    history.push('/tidbs/restore-from-cloud-storage')
                  }}
                >
                  Restore from Cloud Storage
                </Menu.Item>
                <Menu.Item
                  disabled={!createResourceAccess}
                  onClick={() => {
                    history.push('/tidbs/restore-from-another-plan')
                  }}
                >
                  Restore from Another Plan
                </Menu.Item>
              </Menu.Dropdown>
            </Menu>
          </Group>
        )
      }}
    >
      {isError && !firstLoadedRef.current ? (
        <Stack align="center" mt={48}>
          <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>
      ) : (
        <>
          <Flex gap={8}>
            <TextInput
              placeholder="Search Instances"
              value={params.search}
              rightSection={
                !!params.search ? (
                  <IconXClose
                    size={14}
                    sx={{ cursor: 'pointer' }}
                    onClick={() => {
                      setParams({ ...params, search: '' })
                      setPagination({ ...pagination, pageIndex: 0 })
                    }}
                  />
                ) : (
                  <IconSearchSm size={14} sx={{ cursor: 'pointer' }} />
                )
              }
              onChange={(event) => {
                setParams({ ...params, search: event.currentTarget.value })
                setPagination({ ...pagination, pageIndex: 0 })
              }}
            />
            <Select
              data={[
                { label: 'Starter', value: TidbServiceListTidbsServicePlan.Starter },
                { label: 'Essential', value: TidbServiceListTidbsServicePlan.Essential },
                { label: 'Premium', value: TidbServiceListTidbsServicePlan.Premium },
                { label: 'BYOC', value: TidbServiceListTidbsServicePlan.BYOC }
              ]}
              placeholder="Plan"
              clearable={true}
              value={params.servicePlan}
              onChange={(value: TidbServiceListTidbsServicePlan) => {
                setParams({ ...params, servicePlan: value })
                setPagination({ ...pagination, pageIndex: 0 })
              }}
            />
            <ProMultiSelect
              data={regionOptions || []}
              placeholder="Region"
              clearable={true}
              width={204}
              value={params.regionIds}
              onChange={(value) => {
                setParams({ ...params, regionIds: value || [] })
                setPagination({ ...pagination, pageIndex: 0 })
              }}
            />
          </Flex>
          <ProTable
            columns={clusterColumns}
            data={data?.tidbs || []}
            loading={isLoading}
            mantinePaperProps={{ mt: 16, mb: 16 }}
            manualPagination={true}
            renderEmptyRowsFallback={() => {
              if (hasSearch) {
                return <Center h={40}>{isError ? 'Error occurred, please try again later.' : 'No data.'}</Center>
              }
              return (
                <TableFallback height="calc(100vh - 260px)">
                  <TableFallback.Empty title="Get started by creating an instance" desc="" />
                </TableFallback>
              )
            }}
            enablePagination={true}
            state={{ pagination }}
            onPaginationChange={setPagination}
            rowCount={data?.totalSize || 0}
            pagination={{
              showRowsPerPage: true,
              showTotal: true
            }}
          />
        </>
      )}
    </PageShell>
  )
})
