import TimeRangePicker from '@tidb-cloud-uikit/components/TimeRangePicker'
import {
  ActionIcon,
  Anchor,
  Badge,
  Box,
  Button,
  Card,
  Center,
  CopyButton,
  Flex,
  Group,
  HoverCard,
  Loader,
  Menu,
  SimpleGrid,
  Skeleton,
  Stack,
  Tooltip,
  Typography
} from '@tidbcloud/uikit'
import { DEFAULT_TIME_RANGE, TimeRange, TimeRangeValue, toTimeRangeValue } from '@tidbcloud/uikit/biz'
import { IconCheck, IconCopy01, IconDotsHorizontal, IconInfoHexagon } from '@tidbcloud/uikit/icons'
import { Fragment, useCallback, useMemo, useState } from 'react'
import { useQueryClient } from 'react-query'
import { Link, useHistory, useLocation, useParams } from 'react-router-dom'

import { LogoVendors, VendorLogo } from 'dbaas/components'
import dayjs from 'dbaas/components/dayjs'
import { Tag } from 'dbaas/components/tag'
import { AccessDeniedHoverHint, useAccessCheck } from 'dbaas/contexts/access-control'
import AutoRefreshButton, { DEFAULT_AUTO_REFRESH_SECONDS } from 'dbaas/screens/ClusterV2/components/AutoRefreshButton'
import { StoreSizeChartCard } from 'dbaas/screens/NextGen/byoc/configurations/VCPUManagement/StoreSizeChartCard'
import {
  useGetByocAdminNodeVcpu,
  useGetByocObservabilityVcpu
} from 'dbaas/screens/NextGen/byoc/configurations/VCPUManagement/useGetByocDataplaneMetricsSourceURL'
import { VCPUUsageChartCard } from 'dbaas/screens/NextGen/byoc/configurations/VCPUManagement/VCPUUsageChartCard'
import { TiDBPageShell } from 'dbaas/screens/NextGen/tidb-mgmt-container/shared/TiDBPageShell'
import {
  useResourcePoolServiceGetResourcePool,
  useTidbServiceListTidbs
} from 'dbaas/services/api-clients/v2025/tidb-management/v1beta2'
import {
  TidbCloudOpenApinextgenv1beta2Tidb,
  V1beta2ByocVcpuPool
} from 'dbaas/services/api-clients/v2025/tidb-management/v1beta2/interface'
import useStores from 'dbaas/stores/useStores'
import { MixpanelEvents } from 'dbaas/utils/tracking'

import { toResourcePool } from './api'
import { getInstanceStatusColor } from './instanceStatus'
import { ResourcePoolDialogAction, ResourcePoolDialogs } from './ResourcePoolDialogs'
import { ResourcePoolStatusBadge } from './ResourcePoolStatusBadge'

const METRICS_QUICK_RANGES = [
  5 * 60,
  15 * 60,
  30 * 60,
  60 * 60,
  3 * 60 * 60,
  12 * 60 * 60,
  24 * 60 * 60,
  3 * 24 * 60 * 60,
  7 * 24 * 60 * 60,
  14 * 24 * 60 * 60,
  30 * 24 * 60 * 60
]
const MAX_METRICS_RANGE_SECONDS = 30 * 24 * 60 * 60
const SILENT_BYOC_QUERY_REQUEST = { isShowToast: false, isHandleErr: false }
const RESOURCE_POOLS_QUERY_KEY = ['/api/v2025/cloud/v1beta2/resourcePools']

const InstanceList = ({
  count,
  instances,
  loading,
  search,
  canOpenInstances
}: {
  count: number
  instances: TidbCloudOpenApinextgenv1beta2Tidb[]
  loading: boolean
  search: string
  canOpenInstances: boolean
}) => (
  <Card withBorder shadow="none" p="lg">
    <Group gap={4}>
      <Typography variant="title-lg" mb="md">
        Instances in This Pool
      </Typography>
      <Typography variant="title-lg" mb="md" fw={500} c="carbon.6">
        ({count})
      </Typography>
    </Group>
    {loading ? (
      <Center py={60}>
        <Loader size="sm" />
      </Center>
    ) : count === 0 ? (
      <Stack align="center" justify="center" py={60} gap={4}>
        <Typography variant="title-md" c="carbon.7">
          No Instance Yet
        </Typography>
        <Typography variant="body-lg" c="carbon.7" ta="center">
          Instances can be created when the pool is available.
        </Typography>
      </Stack>
    ) : (
      <Stack gap={0} mah={360} sx={{ overflowY: instances.length > 10 ? 'auto' : undefined }}>
        {instances.map((instance) => {
          const content = (
            <Group key={instance.tidbId} justify="space-between">
              <Group gap="xs">
                <Badge variant="dot" color={getInstanceStatusColor(instance.state)} p={0} />
                {instance.displayName}
              </Group>
              {canOpenInstances && <Typography c="carbon.6">→</Typography>}
            </Group>
          )

          return canOpenInstances ? (
            <Anchor
              key={instance.tidbId}
              underline="never"
              c="carbon.8"
              component={Link}
              to={`/tidbs/${instance.tidbId}/overview${search}`}
              sx={(t) => ({
                '&:hover': { background: t.colors.carbon[3] },
                borderRadius: t.radius.sm,
                padding: t.spacing.xs
              })}
              py="4"
              px="8"
            >
              {content}
            </Anchor>
          ) : (
            <Box
              key={instance.tidbId}
              sx={(t) => ({
                color: t.colors.carbon[8],
                borderRadius: t.radius.sm,
                padding: t.spacing.xs
              })}
              py="4"
              px="8"
            >
              {content}
            </Box>
          )
        })}
      </Stack>
    )}
  </Card>
)

export const ResourcePoolDetailsPage = () => {
  const history = useHistory()
  const location = useLocation()
  const { id } = useParams<{ id: string }>()
  const [action, setAction] = useState<ResourcePoolDialogAction>()
  const [metricsTimeRange, setMetricsTimeRange] = useState<TimeRange>(DEFAULT_TIME_RANGE)
  const [metricsTimeRangeValue, setMetricsTimeRangeValue] = useState<TimeRangeValue>(() =>
    toTimeRangeValue(DEFAULT_TIME_RANGE)
  )
  const [metricsRefreshKey, setMetricsRefreshKey] = useState(0)
  const [autoRefreshValue, setAutoRefreshValue] = useState(DEFAULT_AUTO_REFRESH_SECONDS)
  const [metricsStartUnix, metricsEndUnix] = metricsTimeRangeValue
  const queryClient = useQueryClient()
  const {
    store: {
      lastVisitLocation: { orgId, projectId }
    }
  } = useStores()
  const canManageResourcePools = useAccessCheck('ByocResourcePoolManagementAction')
  const resourcePoolQuery = useResourcePoolServiceGetResourcePool(
    id,
    { orgId, projectId },
    {
      query: {
        enabled: !!id && !!orgId && !!projectId,
        retry: 1,
        refetchInterval: (data) => (data?.state === 'CREATING' || data?.state === 'MODIFYING' ? 10_000 : false)
      },
      request: SILENT_BYOC_QUERY_REQUEST
    }
  )
  const instancesQuery = useTidbServiceListTidbs(
    {
      orgId,
      projectId,
      resourcePoolIds: [id],
      pageSize: 100
    },
    {
      query: { enabled: !!id && !!orgId && !!projectId },
      request: SILENT_BYOC_QUERY_REQUEST
    }
  )
  const pool = useMemo(
    () => (resourcePoolQuery.data ? toResourcePool(resourcePoolQuery.data) : undefined),
    [resourcePoolQuery.data]
  )
  const hasPoolCapacity = !!pool?.apiCapacity?.tikv
  const isBusy = pool ? ['Creating', 'Modifying'].includes(pool.status) : false
  const isManagementDisabled = !canManageResourcePools || isBusy
  const isDeleteDisabled = pool ? !canManageResourcePools || pool.status === 'Modifying' || pool.instances > 0 : true
  const metricsPool = useMemo<V1beta2ByocVcpuPool>(
    () => ({
      dataplaneId: pool?.status === 'Active' ? pool.dataplaneId : undefined,
      name: pool?.name,
      resourcePoolId: pool?.id,
      state: pool?.status === 'Modifying' ? 'MODIFYING' : 'AVAILABLE',
      vcpusLimit: pool?.poolVcpuLimit ? String(pool.poolVcpuLimit) : null,
      vcpusUsed: String(pool?.currentVcpuProvision ?? 0)
    }),
    [pool]
  )
  const { data: observabilityVcpu } = useGetByocObservabilityVcpu({
    endUnix: metricsEndUnix,
    orgId,
    projectId,
    regionId: pool?.regionId,
    startUnix: metricsStartUnix
  })
  const { data: adminNodeVcpu } = useGetByocAdminNodeVcpu({
    dataplaneId: pool?.status === 'Active' ? pool.dataplaneId : undefined,
    endUnix: metricsEndUnix,
    orgId,
    projectId,
    regionId: pool?.regionId,
    startUnix: metricsStartUnix
  })
  const additionalVcpuProvision = useMemo(() => {
    const values = [observabilityVcpu, adminNodeVcpu].filter((value): value is number => Number.isFinite(value))
    if (!values.length) {
      return undefined
    }

    return values.reduce((total, value) => total + value, 0)
  }, [adminNodeVcpu, observabilityVcpu])
  const refreshMetrics = useCallback(() => {
    setMetricsTimeRangeValue(toTimeRangeValue(metricsTimeRange))
    setMetricsRefreshKey((key) => key + 1)
  }, [metricsTimeRange])

  const createByocInstance = () => {
    if (!pool) return
    const params = new URLSearchParams(location.search)
    params.set('plan', 'BYOC')
    params.set('resourcePoolId', pool.id)
    history.push(`/tidbs/new?${params.toString()}`)
  }

  if (!pool) {
    return (
      <TiDBPageShell
        title="Resource Pool Details"
        headerProps={{ withBack: true, onBackClick: () => history.push(`/byoc/resource-pools${location.search}`) }}
      >
        <Center h={360}>
          {resourcePoolQuery.isLoading ? (
            <Loader />
          ) : (
            <Stack align="center">
              <Typography c="carbon.7">Resource pool could not be loaded.</Typography>
              <Button variant="default" size="sm" onClick={() => resourcePoolQuery.refetch()}>
                Retry
              </Button>
            </Stack>
          )}
        </Center>
      </TiDBPageShell>
    )
  }

  const infoKV = [
    { label: 'Pool Name', value: pool.name },
    { label: 'Pool ID', value: pool.id, allowCopy: true },
    { label: 'Cloud Provider', value: pool.cloud },
    { label: 'Region', value: pool.region },
    { label: 'Pool CIDR', value: pool.poolCidr },
    { label: 'O11y Cluster CIDR', value: pool.cityClusterCidr },
    { label: 'High Availability', value: pool.highAvailability },
    { label: 'Created by', value: pool.createdBy },
    { label: 'Created at', value: dayjs(pool.createdAt).format('YYYY-MM-DD HH:mm:ss') }
  ]
  return (
    <TiDBPageShell
      title="Resource Pool Details"
      headerProps={{
        withBack: true,
        onBackClick: () => history.push(`/byoc/resource-pools${location.search}`),
        rightSection: (
          <Group>
            <Button
              size="sm"
              disabled={pool.status !== 'Active'}
              onClick={createByocInstance}
              data-mp-event={MixpanelEvents.TidbResource.Create.ButtonClicked}
            >
              Create BYOC Instance
            </Button>
            <Menu withinPortal position="bottom-end" width={180}>
              <Menu.Target>
                <ActionIcon
                  variant="default"
                  size={32}
                  disabled={!canManageResourcePools}
                  aria-label="Resource pool operation dropdown menu"
                  data-testid="resource-pool-details-actions"
                >
                  <IconDotsHorizontal size={16} />
                </ActionIcon>
              </Menu.Target>
              <Menu.Dropdown>
                <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>
          </Group>
        )
      }}
    >
      <Stack gap="xl" pb="xl" data-testid="resource-pool-details-page">
        <Card withBorder shadow="none" p="lg">
          <Group justify="space-between" align="center">
            <Group gap="md">
              <Typography variant="title-lg">{pool.name}</Typography>
              <ResourcePoolStatusBadge status={pool.status} />
              <VendorLogo name={pool.cloud.toLowerCase() as LogoVendors} size={24} />
              <Typography variant="label-lg" c="carbon.7">
                {pool.region}
              </Typography>
            </Group>
            <HoverCard>
              <HoverCard.Target>
                <IconInfoHexagon size={24} c="carbon.8" strokeWidth={1} sx={{ cursor: 'pointer' }} />
              </HoverCard.Target>
              <HoverCard.Dropdown>
                <SimpleGrid cols={2}>
                  {infoKV.map((item) => (
                    <Fragment key={item.label}>
                      <Typography variant="label-lg" c="carbon.7">
                        {item.label}
                      </Typography>
                      <Group>
                        <Typography variant="body-lg" c="carbon.7">
                          {item.value}
                        </Typography>
                        {item.allowCopy && (
                          <CopyButton value={item.value} timeout={2000}>
                            {({ copied, copy }) => (
                              <Tooltip label={copied ? 'Copied' : 'Copy'} withArrow position="right">
                                <ActionIcon variant="transparent" size="sm" c="carbon.8" onClick={copy}>
                                  {copied ? (
                                    <IconCheck size={14} />
                                  ) : (
                                    <IconCopy01 size={14} strokeWidth={2} onClick={copy} />
                                  )}
                                </ActionIcon>
                              </Tooltip>
                            )}
                          </CopyButton>
                        )}
                      </Group>
                    </Fragment>
                  ))}
                </SimpleGrid>
              </HoverCard.Dropdown>
            </HoverCard>
          </Group>
        </Card>

        <Flex gap="xl" align="stretch">
          <Stack gap="md" sx={{ flex: 1, minWidth: 620 }}>
            <Card withBorder shadow="none" p="lg" h={154}>
              <Stack gap={16}>
                <Group justify="space-between" align="flex-start">
                  <Typography variant="title-lg">Pool vCPU Usage</Typography>
                  <AccessDeniedHoverHint id="ByocResourcePoolManagementAction">
                    {({ accessible }) => (
                      <Button
                        variant="default"
                        size="sm"
                        disabled={!accessible || isBusy}
                        onClick={() => setAction('limit')}
                      >
                        {pool.poolVcpuLimit ? 'Update' : 'Setup'} vCPU Limit
                      </Button>
                    )}
                  </AccessDeniedHoverHint>
                </Group>
                <Group gap={64}>
                  <Stack gap={4}>
                    <Typography variant="label-lg" c="carbon.9">
                      Additional vCPU Provision
                    </Typography>
                    <Group gap={4} align="flex-end">
                      <Typography variant="body-md" fz={32} lh="32px">
                        {additionalVcpuProvision ?? '-'}{' '}
                      </Typography>
                      {additionalVcpuProvision !== undefined && (
                        <>
                          <Typography component="span" variant="body-sm">
                            vCPU
                          </Typography>
                          <Typography variant="label-lg" c="green.7">
                            (Free)
                          </Typography>
                        </>
                      )}
                    </Group>
                  </Stack>
                  <Stack gap={4}>
                    <Typography variant="label-lg" c="carbon.9">
                      Current vCPU Provision
                    </Typography>
                    <Group gap={4} align="flex-end">
                      <Typography variant="body-md" fz={32} lh="32px">
                        {pool.currentVcpuProvision ?? '-'}
                      </Typography>
                      <Typography variant="body-lg">vCPU</Typography>
                    </Group>
                  </Stack>
                  <Stack gap={4}>
                    <Typography variant="label-lg" c="carbon.9">
                      Pool vCPU Limit
                    </Typography>
                    <Group gap={4} align="flex-end">
                      <Typography variant="body-md" fz={pool.poolVcpuLimit ? 32 : 20} lh="32px">
                        {pool.poolVcpuLimit ?? 'Not set'}
                      </Typography>
                      {pool.poolVcpuLimit && <Typography variant="body-lg">vCPU</Typography>}
                    </Group>
                  </Stack>
                </Group>
              </Stack>
            </Card>

            <Card withBorder shadow="none" p="lg">
              <Group justify="space-between" mb="lg">
                <Typography variant="title-lg">Metrics</Typography>
                <Group gap="sm">
                  <TimeRangePicker
                    value={metricsTimeRange}
                    onChange={(value) => {
                      setMetricsTimeRange(value)
                      setMetricsTimeRangeValue(toTimeRangeValue(value))
                      setMetricsRefreshKey((key) => key + 1)
                    }}
                    quickRanges={METRICS_QUICK_RANGES}
                    minDateTime={() => dayjs().subtract(30, 'day').startOf('day').toDate()}
                    maxDateTime={() => dayjs().endOf('day').toDate()}
                    maxDuration={MAX_METRICS_RANGE_SECONDS}
                  />
                  <AutoRefreshButton
                    autoRefreshValue={autoRefreshValue}
                    onAutoRefreshChange={setAutoRefreshValue}
                    onRefresh={refreshMetrics}
                  />
                </Group>
              </Group>
              <VCPUUsageChartCard
                chartsOnly
                pool={metricsPool}
                regionId={pool.regionId}
                startUnix={metricsStartUnix}
                endUnix={metricsEndUnix}
                refreshKey={metricsRefreshKey}
              >
                <StoreSizeChartCard
                  orgId={orgId}
                  projectId={projectId}
                  regionId={pool.regionId}
                  dataplaneId={pool.status === 'Active' ? pool.dataplaneId : undefined}
                  resourcePoolId={pool.id}
                  startUnix={metricsStartUnix}
                  endUnix={metricsEndUnix}
                  refreshKey={metricsRefreshKey}
                />
              </VCPUUsageChartCard>
            </Card>
          </Stack>

          <Stack gap="lg" w={340}>
            <InstanceList
              count={instancesQuery.data?.totalSize ?? pool.instances}
              instances={instancesQuery.data?.tidbs ?? []}
              loading={instancesQuery.isLoading}
              search={location.search}
              canOpenInstances={canManageResourcePools}
            />
            <Card withBorder shadow="none" p="lg">
              <Group justify="space-between" mb="md">
                <Typography variant="title-lg">Pool Capacity</Typography>
                <AccessDeniedHoverHint id="ByocResourcePoolManagementAction">
                  {({ accessible }) => (
                    <Button
                      variant="default"
                      size="xs"
                      disabled={!accessible || isBusy}
                      onClick={() => setAction('capacity')}
                    >
                      Update Capacity
                    </Button>
                  )}
                </AccessDeniedHoverHint>
              </Group>
              {hasPoolCapacity ? (
                <Stack gap="md">
                  <Group align="flex-start" wrap="nowrap">
                    <Typography variant="label-lg" c="carbon.7" w={64} sx={{ flexShrink: 0 }}>
                      TiKV
                    </Typography>
                    <Typography variant="body-lg" sx={{ wordBreak: 'normal' }}>
                      {pool.capacity.tikv.vcpu}, {pool.capacity.tikv.memory}
                      <br />
                      {pool.capacity.tikv.storage} storage × {pool.capacity.tikv.nodes} nodes
                    </Typography>
                  </Group>
                  {pool.capacity.tiflash && (
                    <Group align="flex-start" wrap="nowrap">
                      <Typography variant="label-lg" c="carbon.7" w={64} sx={{ flexShrink: 0 }}>
                        TiFlash
                      </Typography>
                      <Typography variant="body-lg" sx={{ wordBreak: 'normal' }}>
                        {pool.capacity.tiflash.vcpu}, {pool.capacity.tiflash.memory}
                        <br />
                        {pool.capacity.tiflash.storage} storage × {pool.capacity.tiflash.nodes} nodes
                      </Typography>
                    </Group>
                  )}
                </Stack>
              ) : (
                <Stack gap="md">
                  <Group align="flex-start" wrap="nowrap">
                    <Skeleton h={16} w={64} mt={4} sx={{ flexShrink: 0 }} />
                    <Stack gap={6} sx={{ flex: 1 }}>
                      <Skeleton h={16} w="100%" />
                      <Skeleton h={16} w="100%" />
                    </Stack>
                  </Group>
                  <Group align="flex-start" wrap="nowrap">
                    <Skeleton h={16} w={64} mt={4} sx={{ flexShrink: 0 }} />
                    <Stack gap={6} sx={{ flex: 1 }}>
                      <Skeleton h={16} w="100%" />
                      <Skeleton h={16} w="100%" />
                    </Stack>
                  </Group>
                </Stack>
              )}
            </Card>
            <Card withBorder shadow="none" p="lg">
              <Group justify="space-between" mb="md">
                <Typography variant="title-lg">{pool.cloud} Resource Tags</Typography>
                <AccessDeniedHoverHint id="ByocResourcePoolManagementAction">
                  {({ accessible }) => (
                    <Button
                      variant="default"
                      size="xs"
                      disabled={!accessible || isBusy}
                      onClick={() => setAction('tags')}
                    >
                      {pool.tags.length ? 'Edit Tags' : 'Add Tags'}
                    </Button>
                  )}
                </AccessDeniedHoverHint>
              </Group>
              {pool.tags.length ? (
                <Group gap="xs">
                  {pool.tags.map((tag) => (
                    <Tag key={`${tag.key}:${tag.value}`} label={`${tag.key} : ${tag.value}`} disabled />
                  ))}
                </Group>
              ) : (
                <Stack align="center" gap={4} py="lg">
                  <Typography variant="title-md" c="carbon.7">
                    No Tag Yet
                  </Typography>
                  <Typography variant="body-lg" c="carbon.7" ta="center">
                    Tags are used to label the AWS resources that support this resource pool.
                  </Typography>
                </Stack>
              )}
            </Card>
          </Stack>
        </Flex>
      </Stack>
      <ResourcePoolDialogs
        action={action}
        opened={!!action}
        pool={pool}
        onClose={() => setAction(undefined)}
        onActionChange={setAction}
        onUpdated={() => {
          resourcePoolQuery.refetch()
          instancesQuery.refetch()
        }}
        onDeleted={async () => {
          await queryClient.invalidateQueries(RESOURCE_POOLS_QUERY_KEY, { refetchInactive: true })
          history.push(`/byoc/resource-pools${location.search}`)
        }}
      />
    </TiDBPageShell>
  )
}

export default ResourcePoolDetailsPage
