import { Alert, Card, Flex, Group, Select, Stack, Typography } from '@tidbcloud/uikit'
import { TimeRange, TimeRangePicker, Dot, toTimeRangeValue } from '@tidbcloud/uikit/biz'
import { IconAlertTriangle } from '@tidbcloud/uikit/icons'
import { useMemo, useState } from 'react'

import dayjs from 'dbaas/components/dayjs'
import AutoRefreshButton, { DEFAULT_AUTO_REFRESH_SECONDS } from 'dbaas/screens/ClusterV2/components/AutoRefreshButton'
import { QUICK_RANGES } from 'dbaas/screens/ClusterV2/features/CalibrateResource/utils/helpers'
import {
  useRegionServiceListByocVcpuPools,
  useRegionServiceListRegionCapacities,
  useRegionServiceListRegions
} from 'dbaas/services/api-clients/v2025/tidb-management/v1beta2'
import {
  Nextgenv1beta2ListByocVcpuPoolsResponse,
  Nextgenv1beta2ListRegionCapacitiesResponseRegionCapacity
} from 'dbaas/services/api-clients/v2025/tidb-management/v1beta2/interface'
import { TidbServiceListTidbsServicePlan } from 'dbaas/services/api-clients/v2025/tidb-management/v1beta2/interface/tidbServiceListTidbsServicePlan'
import useStores from 'dbaas/stores/useStores'

import { StoreSizeChartCard } from './StoreSizeChartCard'
import { useGetByocAdminNodeVcpu, useGetByocObservabilityVcpu } from './useGetByocDataplaneMetricsSourceURL'
import { VCPUProvisionPopover } from './VCPUProvisionPopover'
import { VCPUUsageChartCard } from './VCPUUsageChartCard'

const hasModifyingPool = (data?: Nextgenv1beta2ListByocVcpuPoolsResponse) =>
  data?.groups?.some((group) => group.pools?.some((pool) => pool.state === 'MODIFYING')) ?? false
const SILENT_BYOC_QUERY_REQUEST = { isShowToast: false, isHandleErr: false }

const RegionCard = ({
  capacity,
  onUpdated,
  orgId,
  projectId,
  startUnix,
  endUnix
}: {
  capacity?: Nextgenv1beta2ListRegionCapacitiesResponseRegionCapacity
  onUpdated?: () => void
  orgId: string
  projectId: string
  startUnix: number
  endUnix: number
}) => {
  const { data: byocVcpuPoolsData, refetch: refetchByocVcpuPools } = useRegionServiceListByocVcpuPools(
    {
      orgId,
      projectId,
      cloudProvider: capacity?.region?.cloudProvider,
      regionId: capacity?.region?.regionId
    },
    {
      query: {
        enabled: !!orgId && !!projectId && !!capacity?.region?.regionId,
        refetchOnWindowFocus: false,
        refetchInterval: (data) => (hasModifyingPool(data) ? 10 * 1000 : false)
      },
      request: SILENT_BYOC_QUERY_REQUEST
    }
  )
  const group = useMemo(
    () =>
      byocVcpuPoolsData?.groups?.find((item) => item.region?.regionId === capacity?.region?.regionId) ??
      byocVcpuPoolsData?.groups?.[0],
    [byocVcpuPoolsData?.groups, capacity?.region?.regionId]
  )
  const pools = useMemo(() => group?.pools ?? [], [group?.pools])
  const defaultPool = pools.find((pool) => pool.isDefault) ?? pools[0]
  const dataplaneId = defaultPool?.dataplaneId
  const { data: observabilityVcpu } = useGetByocObservabilityVcpu({
    endUnix,
    orgId,
    projectId,
    regionId: capacity?.region?.regionId,
    startUnix
  })
  const { data: adminNodeVcpu } = useGetByocAdminNodeVcpu({
    dataplaneId,
    endUnix,
    orgId,
    projectId,
    regionId: capacity?.region?.regionId,
    startUnix
  })

  return (
    <Card withBorder data-testid="vcpu-management-region-card">
      <Group justify="space-between" align="center">
        <Group gap="xl" mb="md">
          <Typography variant="title-md">{capacity?.region?.cloudProvider?.toUpperCase()}</Typography>
          <Dot color="carbon" bg="carbon.8" />
          <Typography variant="title-md">{capacity?.region?.displayName}</Typography>
        </Group>
        <VCPUProvisionPopover adminNodeVcpu={adminNodeVcpu} observabilityVcpu={observabilityVcpu} pools={pools} />
      </Group>

      <Stack gap="md">
        {pools.map((pool) => (
          <VCPUUsageChartCard
            key={pool.resourcePoolId ?? pool.name}
            capacity={capacity}
            onUpdated={onUpdated}
            startUnix={startUnix}
            endUnix={endUnix}
            pool={pool}
            onRefetchPools={() => refetchByocVcpuPools()}
          >
            <StoreSizeChartCard
              orgId={orgId}
              projectId={projectId}
              regionId={capacity?.region?.regionId}
              dataplaneId={pool.dataplaneId}
              resourcePoolId={pool.resourcePoolId}
              startUnix={startUnix}
              endUnix={endUnix}
            />
          </VCPUUsageChartCard>
        ))}
      </Stack>
    </Card>
  )
}

export const VCPUManagement = () => {
  const [cloud, setCloud] = useState<string | null>()
  const [region, setRegion] = useState<string | null>()
  const [timeRange, setTimeRange] = useState<TimeRange>({ type: 'relative', value: QUICK_RANGES[6] })
  const [timeRangeValue, setTimeRangeValue] = useState<[number, number]>(() => toTimeRangeValue(timeRange))
  const [autoRefreshValue, setAutoRefreshValue] = useState<number>(DEFAULT_AUTO_REFRESH_SECONDS)

  const {
    store: {
      lastVisitLocation: { orgId, projectId }
    }
  } = useStores()

  const [startTime, endTime] = useMemo(() => {
    const [start, end] = timeRangeValue
    return [dayjs.unix(start).utc().toISOString(), dayjs.unix(end).utc().toISOString()]
  }, [timeRangeValue])

  const { data, refetch } = useRegionServiceListRegionCapacities(
    {
      orgId,
      projectId,
      servicePlan: TidbServiceListTidbsServicePlan.BYOC,
      'usage.startTime': startTime,
      'usage.endTime': endTime
    },
    {
      query: { refetchOnWindowFocus: false, keepPreviousData: true },
      request: SILENT_BYOC_QUERY_REQUEST
    }
  )
  const { data: regionData } = useRegionServiceListRegions(
    {
      orgId,
      projectId,
      servicePlan: TidbServiceListTidbsServicePlan.BYOC,
      pageSize: 100
    },
    {
      query: {
        enabled: !!orgId && !!projectId,
        refetchInterval: 60 * 1000
      },
      request: SILENT_BYOC_QUERY_REQUEST
    }
  )

  const regionOptions = useMemo(
    () => regionData?.regions?.map((v) => ({ label: v?.displayName ?? '', value: v?.regionId ?? '' })),
    [regionData]
  )

  const capacities = data?.capacities
  const filteredCapacities = useMemo(
    () =>
      capacities?.filter((v) => {
        const matchesCloud = !cloud || v.region?.cloudProvider === cloud
        const matchesRegion = !region || v.region?.regionId === region
        return matchesCloud && matchesRegion
      }),
    [capacities, cloud, region]
  )

  return (
    <Stack gap="md">
      <Alert icon={<IconAlertTriangle size={14} />} color="yellow">
        This page lists the vCPU capacity currently provisioned for your TiDB nodes and the resource pool limit that
        controls autoscaling and manual scaling. Stored Data Size shows the amount of your data currently stored in
        databases within each resource pool.
      </Alert>

      <Flex gap="md" justify="space-between" wrap="wrap">
        <Group gap="md" wrap="wrap">
          <Select
            data={[{ value: 'aws', label: 'AWS' }]}
            placeholder="Cloud"
            value={cloud}
            onChange={setCloud}
            w={200}
          />
          <Select data={regionOptions} placeholder="Region" value={region} onChange={setRegion} w={240} />
        </Group>

        <Group gap="md" wrap="wrap">
          <TimeRangePicker
            value={timeRange}
            onChange={(v) => {
              setTimeRange(v)
              setTimeRangeValue(toTimeRangeValue(v))
            }}
            quickRanges={[24 * 60 * 60, 7 * 24 * 60 * 60, 14 * 24 * 60 * 60, 30 * 24 * 60 * 60]}
            maxDateTime={() => dayjs().toDate()}
            disableAbsoluteRanges
          />
          <AutoRefreshButton
            autoRefreshValue={autoRefreshValue}
            onAutoRefreshChange={(v) => {
              setAutoRefreshValue(v)
            }}
            onRefresh={() => {
              setTimeRangeValue(toTimeRangeValue(timeRange))
              refetch()
            }}
          />
        </Group>
      </Flex>
      {filteredCapacities?.map((v) => (
        <RegionCard
          key={v.region?.regionId}
          capacity={v}
          orgId={orgId}
          projectId={projectId}
          startUnix={dayjs(startTime).unix()}
          endUnix={dayjs(endTime).unix()}
          onUpdated={() => refetch()}
        />
      ))}
    </Stack>
  )
}
