import useUrlState from '@ahooksjs/use-url-state'
import { BrushEndListener, BrushEvent } from '@elastic/charts'
import TimeRangePicker from '@tidb-cloud-uikit/components/TimeRangePicker'
import {
  SelectProps,
  Alert,
  Badge,
  Box,
  Card,
  Flex,
  Grid,
  Group,
  SegmentedControl,
  Select,
  Stack,
  Typography,
  useMantineTheme
} from '@tidbcloud/uikit'
import { fromTimeRangeValue, TimeRange, toTimeRangeValue, toURLTimeRange, urlToTimeRange } from '@tidbcloud/uikit/biz'
import { useElementSize } from '@tidbcloud/uikit/hooks'
import dayjs from 'dayjs'
import { observer } from 'mobx-react'
import { useEffect, useMemo, useRef, useState } from 'react'

import { HeroComponent, isHeroQueryReady } from 'dbaas/components/Measurement'
import AutoRefreshButton, { AutoRefreshButtonRef } from 'dbaas/screens/ClusterV2/components/AutoRefreshButton'
import { useSharedTiDBContext } from 'dbaas/screens/NextGen/tidb-mgmt-container/shared/tidb-context'
import { TiDBPageShell } from 'dbaas/screens/NextGen/tidb-mgmt-container/shared/TiDBPageShell'
import { useGetTopruSummary, useGetTopruSummaryplan, useGetTopruUserStats } from 'dbaas/services/useDiagnosisQuery'
import useStores from 'dbaas/stores/useStores'
import { eventTracking } from 'dbaas/utils/tracking'

import { TOP_SQL_TREND_COLOR_ALPHAS, TOP_SQL_TREND_COLOR_NAMES, TOP_SQL_TREND_COLOR_SHADE, withAlpha } from './colors'
import {
  getTopSQLUserLabel,
  getTopSQLUserOptionValue,
  getTopSQLUserRequestValue,
  isTopSQLSystemInternalUserValue
} from './constants'
import { resolveTopSQLIdentity } from './display'
import { onLegendItemOut, onLegendItemOver } from './legendAction'
import SQLExecutionPlanDrawer from './SQLExecutionPlanDrawer'
import TopSQLTable from './TopSQLTable'
import { buildTopSQLExecutionPlans, fillTrendPointGaps } from './transform'
import TrendChart from './TrendChart'
import {
  TopRUSummaryItem,
  TopRUSummaryResponse,
  TopSQLExecutionPlanAnalysisResponse,
  TopSQLTableRecord,
  TopSQLViewMode
} from './types'
import UserShareCard from './UserShareCard'

const QUICK_RANGES = [15 * 60, 30 * 60, 60 * 60, 2 * 60 * 60, 6 * 60 * 60, 12 * 60 * 60, 24 * 60 * 60]
const LIMIT_VALUES = [5, 10, 20, 100]
const LIMIT_OPTIONS = LIMIT_VALUES.map((value) => ({ value: `${value}`, label: `Top ${value}` }))
const ESSENTIAL_LIMIT_OPTIONS = LIMIT_VALUES.filter((value) => value <= 20).map((value) => ({
  value: `${value}`,
  label: `Top ${value}`
}))
const AUTO_REFRESH_OPTIONS = [60, 300]
const DEFAULT_TREND_CHART_WIDTH = 720
const TREND_BAR_WIDTH_PX = 6
const ONE_DAY_SECONDS = 24 * 60 * 60
const MAX_CUSTOM_RANGE_SECONDS = 1 * ONE_DAY_SECONDS
const MIN_SUMMARY_STEP_SECONDS = 1
const SUMMARY_STEP_CANDIDATES = [
  1,
  2,
  5,
  10,
  15,
  30,
  60,
  2 * 60,
  5 * 60,
  10 * 60,
  15 * 60,
  30 * 60,
  60 * 60,
  2 * 60 * 60,
  3 * 60 * 60,
  6 * 60 * 60,
  12 * 60 * 60,
  24 * 60 * 60
] as const
const DEFAULT_TIME_RANGE: TimeRange = {
  type: 'relative',
  value: 60 * 60
}
const DEFAULT_TOP_SQL_AUTO_REFRESH_SECONDS = 0

const renderUserOption: SelectProps['renderOption'] = ({ option }) => (
  <Typography variant="body-lg" fs={isTopSQLSystemInternalUserValue(option.value) ? 'italic' : undefined}>
    {option.label}
  </Typography>
)

interface Filters {
  view: TopSQLViewMode
  top: string
  user: string
  from: string
  to: string
}

const getTopRURecordKey = (sqlDigest?: string) => sqlDigest || '-'

const normalizeSummaryResponse = (payload?: TopRUSummaryResponse | TopRUSummaryItem[]) => {
  if (Array.isArray(payload)) {
    return {
      items: payload,
      step: undefined
    }
  }

  return {
    items: payload?.data || [],
    step: payload?.step
  }
}

const parseStepSeconds = (step?: number) => {
  if (typeof step === 'number' && Number.isFinite(step) && step > 0) {
    return Math.max(MIN_SUMMARY_STEP_SECONDS, Math.floor(step))
  }
}

const getSummaryStepSeconds = (timeRangeSeconds: number, chartWidth: number) => {
  const safeRangeSeconds = Math.max(MIN_SUMMARY_STEP_SECONDS, timeRangeSeconds)
  const safeWidth = Math.max(chartWidth || DEFAULT_TREND_CHART_WIDTH, TREND_BAR_WIDTH_PX)
  const targetBarCount = Math.max(1, Math.floor(safeWidth / TREND_BAR_WIDTH_PX))
  const rawStepSeconds = Math.ceil(safeRangeSeconds / targetBarCount)

  return SUMMARY_STEP_CANDIDATES.find((candidate) => candidate >= rawStepSeconds) || rawStepSeconds
}

const TopRUPageContent: React.FC = observer(() => {
  const tidb = useSharedTiDBContext()
  const {
    store: {
      tenantData: { id: orgId }
    }
  } = useStores()
  const [{ view, top, user, from, to }, setFilters] = useUrlState<Partial<Filters>>(
    {
      view: 'overview',
      top: '10',
      user: undefined,
      from: undefined,
      to: undefined
    },
    { navigateMode: 'replace' }
  )
  const autoRefreshRef = useRef<AutoRefreshButtonRef>(null)
  const trendChartRef = useRef<any>(null)
  const { ref: trendChartSizeRef, width: trendChartWidth } = useElementSize()
  const { colors } = useMantineTheme()
  const [hoveredKey, setHoveredKey] = useState<string>()
  const [selectedRecordKey, setSelectedRecordKey] = useState<string>()
  const [analysisContext, setAnalysisContext] = useState<{ record: TopSQLTableRecord; rank: number } | null>(null)
  const [autoRefreshValue, setAutoRefreshValue] = useState<number>(DEFAULT_TOP_SQL_AUTO_REFRESH_SECONDS)
  const effectiveTop = tidb.computed.isEssentialV2 && Number(top) > 20 ? '20' : top || '10'
  const limitOptions = tidb.computed.isEssentialV2 ? ESSENTIAL_LIMIT_OPTIONS : LIMIT_OPTIONS

  const timeRange = useMemo(() => {
    if (from && to) {
      return urlToTimeRange({ from, to })
    }

    return DEFAULT_TIME_RANGE
  }, [from, to])

  const [queryTimeRangeValue, setQueryTimeRangeValue] = useState<ReturnType<typeof toTimeRangeValue>>(() =>
    toTimeRangeValue(timeRange)
  )
  const [displayedTrendTimeRangeValue, setDisplayedTrendTimeRangeValue] = useState<ReturnType<typeof toTimeRangeValue>>(
    () => toTimeRangeValue(timeRange)
  )
  const [displayedSummaryStepSeconds, setDisplayedSummaryStepSeconds] = useState(() =>
    getSummaryStepSeconds(queryTimeRangeValue[1] - queryTimeRangeValue[0], DEFAULT_TREND_CHART_WIDTH)
  )

  const resetAutoRefreshCountdown = () => {
    autoRefreshRef.current?.resetCountdown()
  }

  useEffect(() => {
    if (tidb.computed.isEssentialV2 && Number(top) > 20) {
      setFilters({ top: '20' })
    }
  }, [setFilters, tidb.computed.isEssentialV2, top])

  useEffect(() => {
    setQueryTimeRangeValue(toTimeRangeValue(timeRange))
  }, [from, to, timeRange])

  const topruUserStatsQuery = useGetTopruUserStats(
    orgId,
    tidb,
    {
      start: String(queryTimeRangeValue[0]),
      end: String(queryTimeRangeValue[1]),
      top: '20'
    },
    {
      query: {
        enabled: !!orgId && !!tidb.tidbId && !tidb.computed.creating && !tidb.computed.restoring,
        refetchOnWindowFocus: false,
        keepPreviousData: true
      }
    }
  )

  const userShareItems = useMemo(
    () =>
      (topruUserStatsQuery.data?.data || [])
        .map((item) => ({
          key: getTopSQLUserOptionValue(item.user),
          label: getTopSQLUserLabel(item.user),
          ru: item.total_ru || 0
        }))
        .sort((left, right) => right.ru - left.ru),
    [topruUserStatsQuery.data]
  )

  const userShareTotalRU = useMemo(() => userShareItems.reduce((sum, item) => sum + item.ru, 0), [userShareItems])
  const userFilterOptions = useMemo(
    () =>
      (topruUserStatsQuery.data?.data || [])
        .map((item) => ({
          value: getTopSQLUserOptionValue(item.user),
          label: getTopSQLUserLabel(item.user)
        }))
        .filter((item, index, items) => items.findIndex((candidate) => candidate.value === item.value) === index),
    [topruUserStatsQuery.data]
  )
  const selectedUser = useMemo(() => {
    if ((view || 'overview') !== 'users') {
      return undefined
    }

    return userFilterOptions.find((option) => option.value === user)?.value
  }, [user, userFilterOptions, view])

  useEffect(() => {
    if ((view || 'overview') !== 'users') {
      return
    }

    if (!userFilterOptions.length) {
      return
    }

    const matchedUser = userFilterOptions.some((option) => option.value === user)
    if (!matchedUser) {
      setFilters({ user: userFilterOptions[0].value })
    }
  }, [setFilters, user, userFilterOptions, view])

  useEffect(() => {
    setAnalysisContext(null)
  }, [selectedUser, view])

  const requestedSummaryStepSeconds = useMemo(
    () => getSummaryStepSeconds(queryTimeRangeValue[1] - queryTimeRangeValue[0], trendChartWidth),
    [queryTimeRangeValue, trendChartWidth]
  )
  const requestedUser = useMemo(() => {
    if ((view || 'overview') !== 'users') {
      return undefined
    }

    return getTopSQLUserRequestValue(selectedUser)
  }, [selectedUser, view])
  const topruSummaryParams = useMemo(
    () =>
      ({
        start: String(queryTimeRangeValue[0]),
        end: String(queryTimeRangeValue[1]),
        top: effectiveTop,
        order_by: 'ru',
        step: requestedSummaryStepSeconds,
        ...(requestedUser !== undefined ? { user: requestedUser } : {})
      }) as Parameters<typeof useGetTopruSummary>[2] & { step?: number },
    [effectiveTop, queryTimeRangeValue, requestedSummaryStepSeconds, requestedUser]
  )
  const topruSummaryQuery = useGetTopruSummary(orgId, tidb, topruSummaryParams, {
    query: {
      enabled:
        !!orgId &&
        !!tidb.tidbId &&
        !tidb.computed.creating &&
        !tidb.computed.restoring &&
        ((view || 'overview') !== 'users' || selectedUser !== undefined),
      refetchOnWindowFocus: false,
      keepPreviousData: true
    }
  })
  const shouldFetchSummaryPlans =
    !!analysisContext && !analysisContext.record.isOthers && !!analysisContext.record.digest
  const topruSummaryPlanParams = useMemo(
    () =>
      ({
        start: String(displayedTrendTimeRangeValue[0]),
        end: String(displayedTrendTimeRangeValue[1]),
        top: effectiveTop,
        digest: analysisContext?.record.digest,
        order_by: 'ru',
        step: displayedSummaryStepSeconds,
        ...(requestedUser !== undefined ? { user: requestedUser } : {})
      }) as Parameters<typeof useGetTopruSummaryplan>[2],
    [
      analysisContext?.record.digest,
      displayedSummaryStepSeconds,
      displayedTrendTimeRangeValue,
      effectiveTop,
      requestedUser
    ]
  )
  const topruSummaryPlanQuery = useGetTopruSummaryplan(orgId, tidb, topruSummaryPlanParams, {
    query: {
      enabled:
        shouldFetchSummaryPlans && !!orgId && !!tidb.tidbId && !tidb.computed.creating && !tidb.computed.restoring,
      refetchOnWindowFocus: false
    }
  })

  const topruSummaryData = topruSummaryQuery.data
  const normalizedSummary = useMemo(
    () => normalizeSummaryResponse(topruSummaryData?.data as TopRUSummaryResponse | TopRUSummaryItem[] | undefined),
    [topruSummaryData]
  )
  const summaryItems = normalizedSummary.items
  const summaryPlanItems = useMemo(() => topruSummaryPlanQuery.data?.data || [], [topruSummaryPlanQuery.data])
  const resolvedSummaryStepSeconds = useMemo(
    () => parseStepSeconds(normalizedSummary.step) || requestedSummaryStepSeconds,
    [normalizedSummary.step, requestedSummaryStepSeconds]
  )
  useEffect(() => {
    if (!topruSummaryQuery.isFetching && topruSummaryQuery.isFetched) {
      setDisplayedTrendTimeRangeValue(queryTimeRangeValue)
      setDisplayedSummaryStepSeconds(resolvedSummaryStepSeconds)
    }
  }, [queryTimeRangeValue, resolvedSummaryStepSeconds, topruSummaryQuery.isFetched, topruSummaryQuery.isFetching])
  const totalSummaryRU = useMemo(
    () => summaryItems.reduce((sum, item) => sum + (item.total_ru || 0), 0),
    [summaryItems]
  )
  const realTrendSeries = useMemo(
    () =>
      summaryItems.map((item) => {
        const identity = resolveTopSQLIdentity(item.sql_text, item.sql_digest)

        return {
          key: getTopRURecordKey(item.sql_digest),
          label: identity.displayName,
          isOthers: identity.isOthers,
          points: fillTrendPointGaps(
            (item.timestamp_sec || []).map((timestamp, index) => ({
              timestamp,
              value: item.total_ru_by_time?.[index] ?? 0
            })),
            displayedSummaryStepSeconds,
            displayedTrendTimeRangeValue
          )
        }
      }),
    [displayedSummaryStepSeconds, displayedTrendTimeRangeValue, summaryItems]
  )
  const overviewRecords = useMemo(
    () =>
      summaryItems.map((item) => {
        const identity = resolveTopSQLIdentity(item.sql_text, item.sql_digest)
        const totalRU = item.total_ru || 0
        const executions = item.exec_count || 0
        const totalLatencyNs = item.duration_ns || 0

        return {
          key: getTopRURecordKey(item.sql_digest),
          trendKey: getTopRURecordKey(item.sql_digest),
          digest: identity.sqlDigest,
          sql: identity.displayName,
          isOthers: identity.isOthers,
          totalRU,
          meanRU: executions > 0 ? totalRU / executions : 0,
          share: totalSummaryRU > 0 ? Number(((totalRU / totalSummaryRU) * 100).toFixed(2)) : 0,
          executions,
          totalLatencyNs,
          meanLatencyNs: executions > 0 ? totalLatencyNs / executions : 0
        }
      }),
    [summaryItems, totalSummaryRU]
  )
  const tableRecords = useMemo(() => {
    return [...overviewRecords].sort((left, right) => {
      if (left.isOthers !== right.isOthers) {
        return left.isOthers ? 1 : -1
      }

      return right.totalRU - left.totalRU
    })
  }, [overviewRecords])
  const displayedTrendSeries = useMemo(() => {
    const seriesOrderMap = new Map(tableRecords.map((record, index) => [record.trendKey, index]))

    return [...realTrendSeries].sort(
      (left, right) =>
        (seriesOrderMap.get(left.key) ?? Number.MAX_SAFE_INTEGER) -
        (seriesOrderMap.get(right.key) ?? Number.MAX_SAFE_INTEGER)
    )
  }, [realTrendSeries, tableRecords])
  const visibleLoading =
    (topruSummaryQuery.isLoading && !topruSummaryQuery.data) ||
    ((view || 'overview') === 'users' && topruUserStatsQuery.isLoading && !topruUserStatsQuery.data)
  const visibleFetching = topruSummaryQuery.isFetching || topruUserStatsQuery.isFetching
  const analysisData = useMemo<TopSQLExecutionPlanAnalysisResponse | undefined>(() => {
    if (!analysisContext) {
      return undefined
    }

    const item = summaryItems.find(
      (summaryItem) => getTopRURecordKey(summaryItem.sql_digest) === analysisContext.record.key
    )
    if (!item) {
      return undefined
    }

    const totalRU = item.total_ru || 0
    const executions = item.exec_count || 0
    const totalLatencyNs = item.duration_ns || 0
    const meanLatencyNs = executions > 0 ? totalLatencyNs / executions : 0
    const identity = resolveTopSQLIdentity(item.sql_text, item.sql_digest)
    const plans = buildTopSQLExecutionPlans({
      items: summaryPlanItems,
      recordKey: analysisContext.record.key,
      statementTotalRU: totalRU,
      stepSeconds: displayedSummaryStepSeconds,
      timeRangeValue: displayedTrendTimeRangeValue
    })

    return {
      statementTemplate: identity.sqlText,
      sqlDigest: identity.sqlDigest,
      isOthers: identity.isOthers,
      rank: analysisContext.rank,
      ru: totalRU,
      meanRU: executions > 0 ? totalRU / executions : 0,
      share: totalSummaryRU > 0 ? Number(((totalRU / totalSummaryRU) * 100).toFixed(2)) : 0,
      planCount: plans.length,
      executions,
      totalLatencyNs,
      meanLatencyNs,
      plans
    }
  }, [
    analysisContext,
    displayedSummaryStepSeconds,
    displayedTrendTimeRangeValue,
    summaryItems,
    summaryPlanItems,
    totalSummaryRU
  ])
  const analysisLoading = !!analysisContext && !analysisData && topruSummaryQuery.isLoading
  const analysisPlansLoading = !!analysisContext && shouldFetchSummaryPlans && topruSummaryPlanQuery.isLoading
  const analysisRecordIndex = useMemo(() => {
    if (!analysisContext) {
      return -1
    }

    return tableRecords.findIndex((item) => item.key === analysisContext.record.key)
  }, [analysisContext, tableRecords])
  const handleOpenAnalysisRecord = (index: number) => {
    const nextRecord = tableRecords[index]
    if (!nextRecord) {
      return
    }

    setSelectedRecordKey(nextRecord.key)
    setAnalysisContext({ record: nextRecord, rank: index + 1 })
  }
  useEffect(() => {
    if (!tableRecords.length) {
      setSelectedRecordKey(undefined)
      return
    }

    const currentExists = tableRecords.some((record) => record.key === selectedRecordKey)
    if (!currentExists) {
      setSelectedRecordKey(undefined)
    }
  }, [selectedRecordKey, tableRecords])

  const trendColorPalette = useMemo(
    () =>
      TOP_SQL_TREND_COLOR_ALPHAS.flatMap((alpha) =>
        TOP_SQL_TREND_COLOR_NAMES.map((colorName) => withAlpha(colors[colorName][TOP_SQL_TREND_COLOR_SHADE], alpha))
      ),
    [colors]
  )

  const seriesColorMap = useMemo(() => {
    return displayedTrendSeries.reduce<Record<string, string>>((map, series, index) => {
      map[series.key] = trendColorPalette[index % trendColorPalette.length]
      return map
    }, {})
  }, [displayedTrendSeries, trendColorPalette])

  const trendSeries = useMemo(
    () =>
      displayedTrendSeries.map((series, index) => ({
        ...series,
        color: seriesColorMap[series.key] || trendColorPalette[index % trendColorPalette.length]
      })),
    [displayedTrendSeries, seriesColorMap, trendColorPalette]
  )

  const handleTableHover = (trendKey: string) => {
    setHoveredKey(trendKey)
    onLegendItemOver(trendChartRef.current, trendKey)
  }

  const handleTableLeave = () => {
    setHoveredKey(undefined)
    onLegendItemOut(trendChartRef.current)
  }

  const handleBrushEnd: BrushEndListener = (event: BrushEvent) => {
    if (!event.x) {
      return
    }

    const brushRange = event.x.map((value) => value / 1000) as [number, number]
    const delta = brushRange[1] - brushRange[0]
    const normalizedRange: [number, number] =
      delta < 60
        ? [Math.floor(brushRange[0] - (60 - delta) / 2), Math.ceil(brushRange[1] + (60 - delta) / 2)]
        : [Math.floor(brushRange[0]), Math.ceil(brushRange[1])]

    eventTracking('Top RU Trend Brush Changed', {
      start: normalizedRange[0],
      end: normalizedRange[1]
    })
    setQueryTimeRangeValue(normalizedRange)
    setFilters(toURLTimeRange(fromTimeRangeValue(normalizedRange)))
    resetAutoRefreshCountdown()
  }

  const handleRefresh = () => {
    const nextTimeRangeValue = toTimeRangeValue(timeRange)
    const isSameTimeWindow =
      nextTimeRangeValue[0] === queryTimeRangeValue[0] && nextTimeRangeValue[1] === queryTimeRangeValue[1]

    if (isSameTimeWindow) {
      eventTracking('Top RU Refresh Button Clicked')
      topruSummaryQuery.refetch()
      topruUserStatsQuery.refetch()
      return
    }

    eventTracking('Top RU Refresh Button Clicked')
    setQueryTimeRangeValue(nextTimeRangeValue)
  }

  return (
    <>
      <TiDBPageShell
        title={
          <Group gap={8} wrap="nowrap" data-testid="top-sql-page-title">
            <span>Top RU</span>
            <Badge variant="outline" size="sm" color="carbon" c="carbon.7" fw={500} data-testid="top-sql-preview-badge">
              Preview
            </Badge>
          </Group>
        }
        headerProps={{ sx: { zIndex: `9 !important` } }}
      >
        <HeroComponent
          ready={isHeroQueryReady({ isFetched: topruSummaryQuery.isFetched, isError: topruSummaryQuery.isError })}
        />
        <Stack gap="lg" data-testid="top-sql-page">
          <Alert color="peacock" data-testid="top-sql-info-banner">
            <Typography variant="body-lg" c="peacock.9">
              Shows SQLs consuming the most RU. Gradual rollout. If no data appears during workload, contact support for
              early access.
            </Typography>
          </Alert>

          <Flex justify="space-between" gap="md" wrap="wrap" data-testid="top-sql-toolbar">
            <Group gap="md" wrap="wrap">
              <SegmentedControl
                data-testid="top-sql-view-mode"
                value={view || 'overview'}
                onChange={(value) => {
                  eventTracking('Top RU View Mode Changed', { viewMode: value })
                  setFilters({
                    view: value as TopSQLViewMode,
                    user: value === 'users' ? user : undefined
                  })
                  resetAutoRefreshCountdown()
                }}
                data={[
                  { label: 'Overview', value: 'overview' },
                  { label: 'Sliced by Users', value: 'users' }
                ]}
              />

              {(view || 'overview') === 'users' && (
                <Select
                  data-testid="top-sql-user-select"
                  w={220}
                  placeholder="Select user"
                  value={selectedUser}
                  renderOption={renderUserOption}
                  disabled={visibleFetching || !userFilterOptions.length}
                  onChange={(value) => {
                    eventTracking('Top RU User Changed', { user: value ?? '' })
                    setFilters({ user: value ?? undefined })
                    resetAutoRefreshCountdown()
                  }}
                  data={userFilterOptions}
                  styles={{
                    input: {
                      fontStyle: isTopSQLSystemInternalUserValue(selectedUser) ? 'italic' : undefined
                    }
                  }}
                />
              )}

              <TimeRangePicker
                value={timeRange}
                onChange={(value) => {
                  eventTracking('Top RU Time Range Change', { timeRange: value })
                  setQueryTimeRangeValue(toTimeRangeValue(value))
                  setFilters(toURLTimeRange(value))
                  resetAutoRefreshCountdown()
                }}
                quickRanges={QUICK_RANGES}
                minDateTime={() =>
                  dayjs()
                    .subtract(tidb.computed.isEssentialV2 ? 7 : 30, 'day')
                    .startOf('day')
                    .toDate()
                }
                maxDateTime={() => dayjs().toDate()}
                maxDuration={MAX_CUSTOM_RANGE_SECONDS}
                datePickerProps={{ allowSingleDateInRange: true }}
                loading={visibleFetching}
              />

              <Select
                data-testid="top-sql-top-select"
                w={108}
                value={effectiveTop}
                disabled={visibleFetching}
                onChange={(value) => {
                  eventTracking('Top RU Limit Change', { top: value || '10' })
                  setFilters({ top: value || '10' })
                  resetAutoRefreshCountdown()
                }}
                data={limitOptions}
              />
            </Group>

            <AutoRefreshButton
              ref={autoRefreshRef}
              autoRefreshValue={autoRefreshValue}
              autoRefreshOptions={AUTO_REFRESH_OPTIONS}
              loading={visibleFetching}
              onAutoRefreshChange={(value) => {
                eventTracking('Top RU Auto Refresh Changed', { autoRefreshValue: value })
                setAutoRefreshValue(value)
              }}
              onRefresh={handleRefresh}
            />
          </Flex>

          <Grid gutter="lg">
            {(view || 'overview') !== 'users' && (
              <Grid.Col span={{ base: 12, lg: 4 }}>
                <UserShareCard
                  loading={topruUserStatsQuery.isLoading && !topruUserStatsQuery.data}
                  totalRU={userShareTotalRU}
                  items={userShareItems}
                />
              </Grid.Col>
            )}

            <Grid.Col span={{ base: 12, lg: (view || 'overview') === 'users' ? 12 : 8 }}>
              <Card withBorder p="md" h={280} data-testid="top-sql-trend-card">
                <Stack gap="lg" h="100%">
                  <Group justify="space-between" align="flex-start">
                    <Typography variant="title-md">Real-Time RU Consumption Trend</Typography>
                  </Group>

                  <Box
                    ref={trendChartSizeRef}
                    h="100%"
                    w="100%"
                    sx={{ flex: 1, minWidth: 0, minHeight: 0, display: 'flex' }}
                  >
                    <TrendChart
                      ref={trendChartRef}
                      data={trendSeries}
                      timeRangeValue={displayedTrendTimeRangeValue}
                      stepSeconds={displayedSummaryStepSeconds}
                      highlightedKey={hoveredKey}
                      onBrushEnd={handleBrushEnd}
                    />
                  </Box>
                </Stack>
              </Card>
            </Grid.Col>
          </Grid>

          <TopSQLTable
            data={tableRecords}
            loading={visibleLoading}
            selectedKey={selectedRecordKey}
            highlightedKey={hoveredKey}
            seriesColorMap={seriesColorMap}
            onSelect={setSelectedRecordKey}
            onHover={handleTableHover}
            onLeave={handleTableLeave}
            onRowClick={(record) => {
              const rank = tableRecords.findIndex((item) => item.key === record.key) + 1
              eventTracking('Top RU Row Clicked', {
                rank: rank || 1,
                sqlDigest: record.digest
              })
              setSelectedRecordKey(record.key)
              setAnalysisContext({ record, rank: rank || 1 })
            }}
          />
        </Stack>
      </TiDBPageShell>

      <SQLExecutionPlanDrawer
        opened={!!analysisContext}
        loading={analysisLoading}
        plansLoading={analysisPlansLoading}
        data={analysisData}
        timeRangeValue={displayedTrendTimeRangeValue}
        currentIndex={analysisRecordIndex}
        totalCount={tableRecords.length}
        onPrev={() => {
          eventTracking('Top RU Detail Previous SQL Clicked', {
            currentIndex: analysisRecordIndex + 1,
            totalCount: tableRecords.length
          })
          handleOpenAnalysisRecord(analysisRecordIndex - 1)
        }}
        onNext={() => {
          eventTracking('Top RU Detail Next SQL Clicked', {
            currentIndex: analysisRecordIndex + 1,
            totalCount: tableRecords.length
          })
          handleOpenAnalysisRecord(analysisRecordIndex + 1)
        }}
        onClose={() => setAnalysisContext(null)}
      />
    </>
  )
})

export default TopRUPageContent
