import { ActionIcon, Button, Flex, Group, Menu, Select, Stack, TextInput, Typography } from '@tidbcloud/uikit'
import { MRT_ColumnDef, ProTable } from '@tidbcloud/uikit/biz'
import { IconDotsHorizontal, IconRefreshCw02, IconSearchSm, IconXClose } from '@tidbcloud/uikit/icons'
import { useEffect, useMemo, useState } from 'react'
import { Link, useHistory, useLocation } from 'react-router-dom'

import { TableFallback } from 'dbaas/components/Table/TableFallback'
import { AccessDeniedHoverHint, useAccessCheck } from 'dbaas/contexts/access-control'
import { TiDBPageShell } from 'dbaas/screens/NextGen/tidb-mgmt-container/shared/TiDBPageShell'
import {
  useResourcePoolServiceGetResourcePool,
  useResourcePoolServiceListResourcePools
} from 'dbaas/services/api-clients/v2025/tidb-management/v1beta2'
import type {
  ResourcePoolServiceListResourcePoolsCloudProvider,
  ResourcePoolServiceListResourcePoolsStatesItem
} from 'dbaas/services/api-clients/v2025/tidb-management/v1beta2/interface'
import useStores from 'dbaas/stores/useStores'
import { MixpanelEvents } from 'dbaas/utils/tracking'

import { toResourcePool, toResourcePoolSummary } from './api'
import { ResourcePoolDialogAction, ResourcePoolDialogs } from './ResourcePoolDialogs'
import { ResourcePoolStatusBadge } from './ResourcePoolStatusBadge'
import { ResourcePool, ResourcePoolStatus } from './types'

const STATUS_OPTIONS: ResourcePoolStatus[] = ['Creating', 'Active', 'Modifying']
const SILENT_BYOC_QUERY_REQUEST = { isShowToast: false, isHandleErr: false }
const DEFAULT_PAGE_SIZE = 20
const API_STATES: Record<ResourcePoolStatus, ResourcePoolServiceListResourcePoolsStatesItem> = {
  Creating: 'CREATING',
  Active: 'ACTIVE',
  Modifying: 'MODIFYING',
  Failed: 'FAILED'
}

const ResourcePoolActions = ({ pool, onUpdated }: { pool: ResourcePool; onUpdated: () => void }) => {
  const [action, setAction] = useState<ResourcePoolDialogAction>()
  const {
    store: {
      lastVisitLocation: { orgId, projectId }
    }
  } = useStores()
  const canManageResourcePools = useAccessCheck('ByocResourcePoolManagementAction')
  const detailsQuery = useResourcePoolServiceGetResourcePool(
    pool.id,
    { orgId, projectId },
    {
      query: {
        enabled: !!action && !!pool.id,
        retry: 1
      },
      request: SILENT_BYOC_QUERY_REQUEST
    }
  )
  const dialogPool = detailsQuery.data ? toResourcePool(detailsQuery.data) : pool
  const isBusy = ['Creating', 'Modifying'].includes(pool.status)
  const isManagementDisabled = !canManageResourcePools || isBusy
  const isDeleteDisabled = !canManageResourcePools || pool.status === 'Modifying' || pool.instances > 0

  return (
    <>
      <Menu withinPortal position="bottom-end" width={190}>
        <Menu.Target>
          <ActionIcon
            variant="subtle"
            disabled={!canManageResourcePools}
            data-testid="resource-pool-actions"
            data-pool-id={pool.id}
          >
            <IconDotsHorizontal size={16} />
          </ActionIcon>
        </Menu.Target>
        <Menu.Dropdown>
          <Menu.Item disabled={isManagementDisabled} onClick={() => setAction('capacity')}>
            Update Capacity
          </Menu.Item>
          <Menu.Item disabled={isManagementDisabled} onClick={() => setAction('limit')}>
            {pool.poolVcpuLimit !== undefined ? 'Update' : 'Setup'} Pool vCPU Limit
          </Menu.Item>
          <Menu.Item disabled={isManagementDisabled} onClick={() => setAction('rename')}>
            Rename
          </Menu.Item>
          <Menu.Item color="red" disabled={isDeleteDisabled} onClick={() => setAction('delete')}>
            Delete
          </Menu.Item>
        </Menu.Dropdown>
      </Menu>
      <ResourcePoolDialogs
        action={action}
        opened={!!action && !!detailsQuery.data}
        pool={dialogPool}
        onClose={() => setAction(undefined)}
        onActionChange={setAction}
        onUpdated={onUpdated}
      />
    </>
  )
}

export const ResourcePoolsList = () => {
  const history = useHistory()
  const location = useLocation()
  const [name, setName] = useState('')
  const [status, setStatus] = useState<string | null>(null)
  const [cloud, setCloud] = useState<string | null>(null)
  const [region, setRegion] = useState<string | null>(null)
  const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: DEFAULT_PAGE_SIZE })
  const [pageTokens, setPageTokens] = useState<Record<number, string | undefined>>({ 0: undefined })
  const {
    store: {
      lastVisitLocation: { orgId, projectId }
    }
  } = useStores()
  const canManageResourcePools = useAccessCheck('ByocResourcePoolManagementAction')

  const resourcePoolsQuery = useResourcePoolServiceListResourcePools(
    {
      orgId,
      projectId,
      displayName: name || undefined,
      states: status ? [API_STATES[status as ResourcePoolStatus]] : undefined,
      cloudProvider: cloud?.toLowerCase() as ResourcePoolServiceListResourcePoolsCloudProvider | undefined,
      regionIds: region ? [region] : undefined,
      pageSize: pagination.pageSize,
      pageToken: pageTokens[pagination.pageIndex]
    },
    {
      query: {
        enabled: !!orgId && !!projectId,
        keepPreviousData: true,
        retry: 1,
        refetchOnWindowFocus: false
      },
      request: SILENT_BYOC_QUERY_REQUEST
    }
  )
  const data = useMemo(
    () => (resourcePoolsQuery.data?.resourcePools ?? []).map(toResourcePoolSummary),
    [resourcePoolsQuery.data?.resourcePools]
  )

  useEffect(() => {
    const nextPageToken = resourcePoolsQuery.data?.nextPageToken
    if (!nextPageToken) {
      return
    }
    setPageTokens((current) => {
      if (current[pagination.pageIndex + 1] === nextPageToken) {
        return current
      }
      return { ...current, [pagination.pageIndex + 1]: nextPageToken }
    })
  }, [pagination.pageIndex, resourcePoolsQuery.data?.nextPageToken])

  const resetPagination = () => {
    setPageTokens({ 0: undefined })
    setPagination((current) => ({ ...current, pageIndex: 0 }))
  }
  const regionOptions = useMemo(
    () =>
      Array.from(new Set(data.map((pool) => pool.regionId).filter(Boolean))).map((regionId) => ({
        label: regionId,
        value: regionId
      })),
    [data]
  )

  const columns = useMemo<MRT_ColumnDef<ResourcePool>[]>(
    () => [
      {
        header: 'Name',
        Header: () => <Typography pl={16}>Name</Typography>,
        accessorKey: 'name',
        size: 220,
        accessorFn: (pool) => (
          <Typography
            component={Link}
            to={`/byoc/resource-pools/${pool.id}${location.search}`}
            variant="label-lg"
            c="peacock.7"
            ml={16}
            truncate
          >
            {pool.name}
          </Typography>
        )
      },
      {
        header: 'Status',
        accessorKey: 'status',
        accessorFn: (pool) => <ResourcePoolStatusBadge status={pool.status} />
      },
      { header: 'Cloud', accessorKey: 'cloud' },
      { header: 'Region', accessorKey: 'region', size: 220 },
      { header: 'Instances', accessorKey: 'instances' },
      { header: 'Created at', accessorKey: 'createdAt', size: 190 },
      {
        header: '',
        id: 'actions',
        size: 48,
        enableSorting: false,
        accessorFn: (pool) => <ResourcePoolActions pool={pool} onUpdated={() => resourcePoolsQuery.refetch()} />
      }
    ],
    [location.search, resourcePoolsQuery]
  )

  const clearFilters = () => {
    setName('')
    setStatus(null)
    setCloud(null)
    setRegion(null)
    resetPagination()
  }

  return (
    <TiDBPageShell
      title="Resource Pools"
      headerProps={{
        rightSection: (
          <AccessDeniedHoverHint id="ByocResourcePoolManagementAction">
            {({ accessible }) => (
              <Button
                size="sm"
                disabled={!accessible}
                onClick={() => history.push(`/byoc/resource-pools/new${location.search}`)}
                data-mp-event={MixpanelEvents.TidbResource.Create.ButtonClicked}
                data-testid="resource-pools-create-button"
              >
                Create Resource Pool
              </Button>
            )}
          </AccessDeniedHoverHint>
        )
      }}
    >
      <Stack gap="4" pb="xl" data-testid="resource-pools-list-page">
        <Flex justify="space-between" align="center" gap="md" wrap="wrap">
          <Group gap="sm" wrap="wrap">
            <TextInput
              value={name}
              onChange={(event) => {
                setName(event.currentTarget.value)
                resetPagination()
              }}
              placeholder="Search Name"
              rightSection={
                name ? (
                  <IconXClose
                    size={16}
                    cursor="pointer"
                    onClick={() => {
                      setName('')
                      resetPagination()
                    }}
                  />
                ) : (
                  <IconSearchSm size={16} />
                )
              }
              w={240}
            />
            <Select
              value={status}
              onChange={(value) => {
                setStatus(value)
                resetPagination()
              }}
              data={STATUS_OPTIONS}
              placeholder="Status"
              clearable
              w={160}
            />
            <Select
              value={cloud}
              onChange={(value) => {
                setCloud(value)
                resetPagination()
              }}
              data={['AWS', 'Azure']}
              placeholder="Cloud"
              clearable
              w={160}
            />
            <Select
              value={region}
              onChange={(value) => {
                setRegion(value)
                resetPagination()
              }}
              data={regionOptions}
              placeholder="Region"
              clearable
              w={220}
            />
            <Button variant="subtle" onClick={clearFilters}>
              Clear Filter
            </Button>
          </Group>
          <ActionIcon variant="subtle" aria-label="Refresh resource pools" onClick={() => resourcePoolsQuery.refetch()}>
            <IconRefreshCw02 size={16} />
          </ActionIcon>
        </Flex>

        <ProTable
          columns={columns}
          data={data}
          loading={resourcePoolsQuery.isLoading || resourcePoolsQuery.isFetching}
          emptyMessage="No Resource Pools"
          enablePagination
          manualPagination
          enableColumnPinning
          state={{ pagination }}
          onPaginationChange={(updater) => {
            const nextPagination = typeof updater === 'function' ? updater(pagination) : updater
            if (nextPagination.pageSize !== pagination.pageSize) {
              setPageTokens({ 0: undefined })
              setPagination({ pageIndex: 0, pageSize: nextPagination.pageSize })
              return
            }
            if (nextPagination.pageIndex > 0 && !pageTokens[nextPagination.pageIndex]) {
              return
            }
            setPagination(nextPagination)
          }}
          rowCount={resourcePoolsQuery.data?.totalSize || 0}
          pagination={{ showRowsPerPage: true, showTotal: true }}
          mantinePaperProps={{ mt: 16, mb: 16 }}
          data-testid="resource-pools-table"
          renderEmptyRowsFallback={() => {
            return (
              <TableFallback height="calc(100vh - 260px)">
                <TableFallback.Empty
                  title={canManageResourcePools ? 'Get started by creating a resource' : 'No Resource Pools'}
                  desc=""
                />
              </TableFallback>
            )
          }}
        />
      </Stack>
    </TiDBPageShell>
  )
}

export default ResourcePoolsList
