import useUrlState from '@ahooksjs/use-url-state'
import { ActionIcon, Box, Button, Center, Group, Stack, TextInput, Typography } from '@tidbcloud/uikit'
import { MRT_ColumnDef, ProMultiSelect, ProTable } from '@tidbcloud/uikit/biz'
import { useDebouncedValue, useMediaQuery } from '@tidbcloud/uikit/hooks'
import { IconRefreshCw02, IconSearchSm, IconXCircle, IconXClose } from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'
import { useMemo, useRef, useState } from 'react'
import { Link, useHistory } from 'react-router-dom'

import { HeroComponent, isHeroQueryReady } from 'dbaas/components/Measurement'
import TimeComponent from 'dbaas/components/TimeComponent'
import { BFFTiDB, getBFFTiDB } from 'dbaas/features/ClusterManagement/tidb'
import { getCloudProviderLabel } from 'dbaas/features/Project'
import { ProjectType } from 'dbaas/features/Project'
import { StateTag } from 'dbaas/screens/Cluster/ClusterInfo'
import { ClusterOperations } from 'dbaas/screens/Cluster/Operations'
import { TableFallback } from 'dbaas/screens/ClusterV2/components/PausedStatus'
import { StarterListOperation } from 'dbaas/screens/ConsoleV2/features/Clusters/StarterListOperation'
import { useRequestSupport } from 'dbaas/screens/HelpCenter/RequestSupport/helper'
import { useEssentialV2Enabled } from 'dbaas/screens/NextGen/my-tidb-creation/shared/use-essential-v2-enabled'
import { useVirtualProjectId } from 'dbaas/screens/NextGen/my-tidb-creation/shared/use-virtual-project-id'
import { ServicePlanTag } from 'dbaas/screens/NextGen/shared/tidb-instance/service-plan/ServicePlanTag'
import { CentralUserProfileProject } from 'dbaas/services/account/interface'
import {
  useRegionServiceListRegions,
  useTiDBServiceListTidbs
} from 'dbaas/services/api-clients/v2023/cluster-management/v1beta2'
import { V1beta2ListRegionsRequestViewMode } from 'dbaas/services/api-clients/v2023/cluster-management/v1beta2/interface'
import {
  TidbServiceListTidbsServicePlan,
  V1beta1RegionCloudProvider
} from 'dbaas/services/api-clients/v2025/tidb-management/v1beta2/interface'
import useStores from 'dbaas/stores/useStores'

import { PremiumListOperation } from '../premium/list/ListOperation'

import { MyTiDBViewToolbar } from './ViewToolbar'

const DEFAULT_PAGE_SIZE = 10

interface UrlStateParams {
  search?: string
  tidbId?: string
  servicePlans?: string | string[]
  regionIds?: string | string[]
  projectIds?: string | string[]
  pageIndex?: string
  pageSize?: string
}

export const MyTiDBListView = observer(
  ({
    viewMode,
    onSwitchView,
    isPremiumReservedEnabled
  }: {
    viewMode: 'list' | 'project'
    onSwitchView: (value: string) => void
    isPremiumReservedEnabled: boolean
  }) => {
    const history = useHistory()
    const {
      store: { tenantData, allProjects },
      actions: { updateLastVisitLocation }
    } = useStores()

    const [urlState, setUrlState] = useUrlState<UrlStateParams>(
      {
        search: undefined,
        tidbId: undefined,
        servicePlans: undefined,
        regionIds: undefined,
        projectIds: undefined,
        pageIndex: '0',
        pageSize: `${DEFAULT_PAGE_SIZE}`
      },
      { navigateMode: 'replace' }
    )

    const normalizeArrayParam = <T extends string>(value: string | string[] | undefined): T[] => {
      if (!value) return []
      if (Array.isArray(value)) return value as T[]
      return [value as T]
    }

    const params = {
      search: urlState.search || '',
      tidbId: urlState.tidbId || '',
      servicePlans: normalizeArrayParam<TidbServiceListTidbsServicePlan>(urlState.servicePlans),
      regionIds: normalizeArrayParam<string>(urlState.regionIds),
      projectIds: normalizeArrayParam<string>(urlState.projectIds)
    }
    const pagination = {
      pageIndex: Number(urlState.pageIndex || 0),
      pageSize: Number(urlState.pageSize || DEFAULT_PAGE_SIZE)
    }

    const [debouncedParams] = useDebouncedValue(params, 300)
    const isEssentialV2Enabled = useEssentialV2Enabled()
    const effectiveServicePlans =
      isEssentialV2Enabled && debouncedParams.servicePlans.includes(TidbServiceListTidbsServicePlan.Essential)
        ? [...new Set([...debouncedParams.servicePlans, TidbServiceListTidbsServicePlan.Essential_V2])]
        : debouncedParams.servicePlans
    const firstLoadedRef = useRef(false)
    const [refetching, setRefetching] = useState(false)
    const { open: openSupport } = useRequestSupport()
    const virtualProjectId = useVirtualProjectId()
    const virtualProject = virtualProjectId
      ? ({
          id: virtualProjectId,
          name: '(Out of project)',
          org_id: tenantData.id,
          is_cross_account: false,
          type: ProjectType.TIDBX_VIRTUAL
        } as CentralUserProfileProject)
      : undefined
    const orgProjects = allProjects.filter(
      (project) => project.org_id === tenantData.id && project.type !== ProjectType.TIDBX_VIRTUAL
    )
    const currentOrgProjects = virtualProject ? [virtualProject, ...orgProjects] : orgProjects

    const hasSearch =
      debouncedParams.search ||
      debouncedParams.tidbId.trim() ||
      effectiveServicePlans.length > 0 ||
      debouncedParams.regionIds.length > 0 ||
      debouncedParams.projectIds.length > 0

    const { data, isLoading, isFetched, isError, refetch } = useTiDBServiceListTidbs(
      {
        orgId: tenantData.id,
        pageSize: pagination.pageSize,
        skip: pagination.pageIndex * pagination.pageSize,
        servicePlans: effectiveServicePlans,
        projectIds: debouncedParams.projectIds.includes(virtualProject?.id || '')
          ? [...debouncedParams.projectIds, '0']
          : debouncedParams.projectIds,
        name: debouncedParams.search,
        tidbIds: debouncedParams.tidbId.trim() ? [debouncedParams.tidbId.trim()] : undefined,
        regionIds: debouncedParams.regionIds
      },
      {
        query: {
          retry: 3,
          retryDelay: 5 * 1000,
          refetchOnWindowFocus: (query) => !query.state.error,
          onSuccess: () => {
            setRefetching(false)
            if (!firstLoadedRef.current) {
              firstLoadedRef.current = true
            }
          },
          onError: () => {
            setRefetching(false)
          },
          select: (resp) => ({
            ...resp,
            tidbs: resp.tidbs?.map((tidb) => getBFFTiDB(tidb))
          })
        }
      }
    )

    const { data: regionData } = useRegionServiceListRegions(
      {
        orgId: tenantData.id,
        viewMode: V1beta2ListRegionsRequestViewMode.FLAT
      },
      {
        query: {
          retry: 3,
          retryDelay: 5 * 1000
        }
      }
    )

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

      const groupedRegions = regionData.flatView.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 projectOptions = currentOrgProjects.map((project) => ({
      value: project.id,
      label: project.name
    }))

    const projectNameMap = currentOrgProjects.reduce(
      (acc, project) => {
        acc[project.id] = project
        return acc
      },
      {} as Record<string, CentralUserProfileProject>
    )

    const handleClearFilters = () => {
      setUrlState({
        search: undefined,
        tidbId: undefined,
        servicePlans: undefined,
        regionIds: undefined,
        projectIds: undefined,
        pageIndex: '0'
      })
    }

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

    const clusterColumns: MRT_ColumnDef<BFFTiDB>[] = [
      {
        header: 'Name',
        Header: () => <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={() => {
                updateLastVisitLocation({ projectId: row.projectId })
                history.push(`/tidbs/${row.tidbId}/overview`)
              }}
            >
              {row.displayName}
            </Typography>
          )
        }
      },
      {
        header: 'Status',
        accessorFn: (row) => (
          <Group>
            <StateTag displayStatus={row.state} />
          </Group>
        ),
        maxSize: 100
      },
      {
        header: 'Plan',
        accessorFn: (row) =>
          row.servicePlan ? (
            <ServicePlanTag
              servicePlan={row.instance?.computed.isCassandra ? 'Cassandra Integration' : row.servicePlan}
            />
          ) : (
            '-'
          ),
        size: 160
      },
      {
        header: 'Project',
        accessorFn: (row) => {
          const name = projectNameMap[row.projectId]?.name || ''
          if (
            !row.projectId ||
            row.projectId === '0' ||
            projectNameMap[row.projectId]?.type === ProjectType.TIDBX_VIRTUAL ||
            !name
          ) {
            return '-'
          }
          if (projectNameMap[row.projectId]?.type === ProjectType.TIDBX) {
            return projectNameMap[row.projectId]?.name || row.projectId
          }
          return (
            <Box
              component={Link}
              to={`/project/network-access?orgId=${tenantData.id}&projectId=${row.projectId}`}
              sx={{ textDecoration: 'none !important' }}
              onClick={() => {
                updateLastVisitLocation({ projectId: row.projectId })
              }}
            >
              {name}
            </Box>
          )
        }
      },
      {
        header: 'Cloud',
        accessorFn: (row) => getCloudProviderLabel(row.cloudProvider),
        size: 100
      },
      {
        header: 'Region',
        accessorFn: (row) => row.regionDisplayName
      },
      {
        header: 'Created At',
        accessorFn: (row) => <TimeComponent time={row.createTime || ''} format="YYYY-MM-DD HH:mm:ss" />
      },
      {
        id: 'Action',
        header: '',
        accessorFn: (row) => {
          if (row.cluster?.dedicated) {
            return (
              <ClusterOperations
                cluster={row.cluster}
                position="bottom-end"
                actionVariant="subtle"
                from="my-tidb"
                onMenuOpen={() => {
                  updateLastVisitLocation({ projectId: row.projectId })
                }}
              />
            )
          }
          if (row.cluster?.serverless) {
            return (
              <StarterListOperation
                cluster={row.cluster.serverless}
                onMenuOpen={() => {
                  updateLastVisitLocation({ projectId: row.projectId })
                }}
              />
            )
          }
          if (row.instance) {
            return (
              <PremiumListOperation
                tidb={row.instance}
                onMenuOpen={() => {
                  updateLastVisitLocation({ projectId: row.projectId })
                }}
              />
            )
          }
          return null
        },
        size: 80
      }
    ]

    return (
      <Box data-testid="my-tidb-list-view">
        <HeroComponent ready={isHeroQueryReady({ isFetched, isError })} />
        {isError && !firstLoadedRef.current ? (
          <Stack align="center" mt={48} data-testid="my-tidb-error-state">
            <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>
        ) : (
          <>
            <MyTiDBViewToolbar
              viewMode={viewMode}
              onSwitchView={onSwitchView}
              actions={
                <ActionIcon
                  onClick={() => {
                    setRefetching(true)
                    refetch().finally(() => {
                      setRefetching(false)
                    })
                  }}
                  variant="subtle"
                  data-mp-event="My TiDB Refresh Button Clicked"
                  data-testid="my-tidb-refresh-button"
                >
                  <IconRefreshCw02 size={16} />
                </ActionIcon>
              }
            >
              <TextInput
                placeholder="Search Name"
                w={220}
                value={params.search}
                data-testid="my-tidb-search-input"
                rightSection={
                  params.search ? (
                    <IconXClose
                      size={14}
                      sx={{ cursor: 'pointer' }}
                      onClick={() => {
                        setUrlState({ search: undefined, pageIndex: '0' })
                      }}
                    />
                  ) : (
                    <IconSearchSm size={14} sx={{ cursor: 'pointer' }} />
                  )
                }
                onChange={(event) => {
                  setUrlState({ search: event.currentTarget.value || undefined, pageIndex: '0' })
                }}
              />
              <TextInput
                placeholder="Search ID"
                w={220}
                value={params.tidbId}
                data-testid="my-tidb-id-search-input"
                rightSection={
                  params.tidbId ? (
                    <IconXClose
                      size={14}
                      sx={{ cursor: 'pointer' }}
                      onClick={() => {
                        setUrlState({ tidbId: undefined, pageIndex: '0' })
                      }}
                    />
                  ) : (
                    <IconSearchSm size={14} sx={{ cursor: 'pointer' }} />
                  )
                }
                onChange={(event) => {
                  setUrlState({ tidbId: event.currentTarget.value || undefined, pageIndex: '0' })
                }}
              />
              <ProMultiSelect
                data={[
                  { label: 'Starter', value: TidbServiceListTidbsServicePlan.Starter },
                  { label: 'Essential', value: TidbServiceListTidbsServicePlan.Essential },
                  { label: 'Premium', value: TidbServiceListTidbsServicePlan.Premium },
                  ...(isPremiumReservedEnabled
                    ? [
                        {
                          label: 'Premium Reserved',
                          value: TidbServiceListTidbsServicePlan.Premium_Reserved
                        }
                      ]
                    : []),
                  { label: 'BYOC', value: TidbServiceListTidbsServicePlan.BYOC },
                  { label: 'Dedicated', value: 'Dedicated' }
                ]}
                placeholder="Plan"
                clearable
                width={190}
                value={params.servicePlans}
                searchable
                onChange={(value: TidbServiceListTidbsServicePlan[]) => {
                  setUrlState({ servicePlans: value?.length ? value : undefined, pageIndex: '0' })
                }}
                data-testid="my-tidb-plan-filter"
              />
              <ProMultiSelect
                data={regionOptions}
                placeholder="Region"
                clearable
                width={190}
                searchable
                value={params.regionIds}
                onChange={(value) => {
                  setUrlState({ regionIds: value?.length ? value : undefined, pageIndex: '0' })
                }}
                data-testid="my-tidb-region-filter"
              />
              <ProMultiSelect
                data={projectOptions}
                placeholder="Project"
                clearable
                width={190}
                value={params.projectIds}
                searchable
                onChange={(value) => {
                  setUrlState({ projectIds: value?.length ? value : undefined, pageIndex: '0' })
                }}
                data-testid="my-tidb-project-filter"
              />
              <Button onClick={handleClearFilters} variant="subtle" data-testid="my-tidb-clear-filter-button">
                Clear Filter
              </Button>
            </MyTiDBViewToolbar>

            <Box data-testid="my-tidb-list-table-container">
              <ProTable
                columns={clusterColumns}
                data={data?.tidbs || []}
                loading={isLoading || refetching}
                mantinePaperProps={{ mt: 16, mb: 16 }}
                manualPagination
                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 a resource" desc="" />
                    </TableFallback>
                  )
                }}
                enablePagination
                state={{ pagination }}
                onPaginationChange={(updater) => {
                  const newPagination = typeof updater === 'function' ? updater(pagination) : updater
                  setUrlState({ pageIndex: String(newPagination.pageIndex), pageSize: String(newPagination.pageSize) })
                }}
                rowCount={data?.totalSize || 0}
                pagination={{ showRowsPerPage: true, showTotal: true }}
                data-testid="my-tidb-list-table"
              />
            </Box>
          </>
        )}
      </Box>
    )
  }
)

export default MyTiDBListView
