import { BrushEndListener, BrushEvent } from '@elastic/charts'
import { Alert, Box, Card, Flex, Grid, Group, Select, Stack, Typography, useMantineTheme } from '@tidbcloud/uikit'
import { toTimeRangeValue } from '@tidbcloud/uikit/biz'
import { useElementSize } from '@tidbcloud/uikit/hooks'
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useHistory } from 'react-router-dom'

import config from 'config'
import { HeroComponent } from 'dbaas/components/Measurement'
import { SharedCluster } from 'dbaas/features/ClusterManagement/cluster'
import { isClusterInvalid, PausedStatus } from 'dbaas/screens/ClusterV2/components/PausedStatus'
import {
  TOP_SQL_TREND_COLOR_ALPHAS,
  TOP_SQL_TREND_COLOR_NAMES,
  TOP_SQL_TREND_COLOR_SHADE,
  withAlpha
} from 'dbaas/screens/NextGen/premium/top-sql/colors'
import { onLegendItemOut, onLegendItemOver } from 'dbaas/screens/NextGen/premium/top-sql/legendAction'
import TrendChart from 'dbaas/screens/NextGen/premium/top-sql/TrendChart'
import { SharedTiDB } from 'dbaas/screens/NextGen/shared/model/shared-tidb-state'
import {
  useGetStatementsFieldValues,
  useGetStatementsFieldValuesForCluster,
  useGetStatementsList,
  useGetStatementsListForCluster,
  useGetStatementsSummary,
  useGetStatementsSummaryForCluster,
  useGetStatementsTopstats,
  useGetStatementsTopstatsForCluster
} from 'dbaas/services/useDiagnosisQuery'
import useStores from 'dbaas/stores/useStores'
import { eventTracking } from 'dbaas/utils/tracking'

import { useStatementListUrlState } from '../Statement/List/url-state'
import { StatementModel } from '../Statement/utils/type'

import ContributorCard from './ContributorCard'
import ListTable from './ListTable'
import StatementFilters from './StatementFilters'
import {
  aggregateStatementsForTable,
  buildStatementContributorSummaryFromTopstats,
  buildStatementTrendSeriesFromSummary,
  formatStatementMetricValue,
  getDefaultStatementMetric,
  getStatementMetricOptions,
  getStatementRecordKey,
  getStatementSummaryStepSeconds,
  normalizeStatementSummaryResponse,
  STATEMENT_V2_FIELDS,
  STATEMENT_V2_DEFAULT_TIME_RANGE,
  StatementMetricKey,
  StatementSummaryDimension
} from './statementV2'

const FEATURE_NAME_V2 = 'SQL Statement V2'
type StatementFieldValuesField = 'stmt_types' | 'sample_user' | 'schema_name' | 'table_names'

const STATEMENT_FIELD_VALUES_LIMIT = 2000
const uniqueStrings = (values: string[]) => [...new Set(values.filter(Boolean))]
const normalizeTableNames = (values: string[]) =>
  uniqueStrings(values.flatMap((value) => value.split(',').map((table) => table.trim())))

const isStatementListRow = (value: unknown): value is StatementModel => {
  if (!value || typeof value !== 'object' || Array.isArray(value)) {
    return false
  }

  return ['digest', 'digest_text', 'schema_name', 'sample_user', 'stmt_type'].some((key) => key in value)
}

const getStatementListRows = (payload: unknown): StatementModel[] => {
  if (Array.isArray(payload)) {
    return payload.some(isStatementListRow) ? (payload as StatementModel[]) : []
  }

  if (!payload || typeof payload !== 'object') {
    return []
  }

  const record = payload as Record<string, unknown>

  for (const key of ['data', 'rows', 'items', 'list', 'result']) {
    const nestedRows = getStatementListRows(record[key])

    if (nestedRows.length) {
      return nestedRows
    }
  }

  const objectValues = Object.values(record)

  if (objectValues.length && objectValues.every(isStatementListRow)) {
    return objectValues as StatementModel[]
  }

  return []
}

const useStatementFieldValues = ({
  orgId,
  activeProjectId,
  currentCluster,
  currentTidb,
  isPremiumSource,
  clusterEnabled,
  nextGenEnabled,
  beginTime,
  endTime,
  field,
  enabled
}: {
  orgId: string
  activeProjectId: string
  currentCluster: SharedCluster
  currentTidb: SharedTiDB
  isPremiumSource: boolean
  clusterEnabled: boolean
  nextGenEnabled: boolean
  beginTime: number
  endTime: number
  field: StatementFieldValuesField
  enabled: boolean
}) => {
  const params = useMemo(
    () => ({
      begin_time: beginTime,
      end_time: endTime,
      field,
      limit: STATEMENT_FIELD_VALUES_LIMIT
    }),
    [beginTime, endTime, field]
  )

  const clusterQuery = useGetStatementsFieldValuesForCluster(orgId, activeProjectId, currentCluster, params, {
    query: {
      enabled: clusterEnabled && enabled,
      refetchOnWindowFocus: false,
      keepPreviousData: true,
      staleTime: Infinity
    }
  })
  const nextGenQuery = useGetStatementsFieldValues(orgId, currentTidb, params, {
    query: {
      enabled: nextGenEnabled && enabled,
      refetchOnWindowFocus: false,
      keepPreviousData: true,
      staleTime: Infinity
    }
  })
  const query = isPremiumSource ? nextGenQuery : clusterQuery

  return {
    data: Array.isArray(query.data) ? query.data : [],
    isFetching: query.isFetching
  }
}

const EMPTY_COMPUTED: SharedTiDB['computed'] = {
  clusterType: 'Unselected',
  ready: false,
  pausing: false,
  paused: false,
  upgrading: false,
  resuming: false,
  scaling: false,
  unavailable: false,
  recovering: false,
  deleted: false,
  maintaining: false,
  importing: false,
  loading: false,
  active: false,
  inactive: false,
  deleting: false,
  creating: false,
  modifying: false,
  restoring: false,
  isServerless: false,
  isDedicated: false,
  isStarter: false,
  isEssential: false,
  isEssentialV2: false,
  isPremium: false,
  isPremiumReserved: false,
  isBYOC: false,
  isCassandra: false,
  projectId: '',
  originalProjectId: ''
}

const EMPTY_CLUSTER = {
  id: '',
  name: '',
  displayName: '',
  provider: '',
  region: '',
  regionId: '',
  regionDisplayName: '',
  version: '',
  createTime: '',
  servicePlan: undefined,
  state: undefined,
  computed: EMPTY_COMPUTED
} as unknown as SharedCluster

const EMPTY_TIDB = {
  tidbId: '',
  displayName: '',
  regionId: '',
  cloudProvider: '',
  servicePlan: undefined,
  state: undefined,
  computed: EMPTY_COMPUTED
} as unknown as SharedTiDB

interface StatementV2PageProps {
  cluster?: SharedCluster
  tidb?: SharedTiDB
  detailPathBase?: string
}

const StatementV2Page: React.FC<React.PropsWithChildren<StatementV2PageProps>> = ({
  cluster,
  tidb,
  detailPathBase
}) => {
  const {
    store: {
      tenantData: { id: orgId },
      activeProjectId
    }
  } = useStores()
  const history = useHistory()
  const { timeRange, kinds, search, dbs, sampleUsers, tableNames, sortRules, setSortRules } = useStatementListUrlState(
    STATEMENT_V2_DEFAULT_TIME_RANGE
  )
  const { colors } = useMantineTheme()
  const trendChartRef = useRef<any>(null)
  const { ref: trendChartSizeRef, width: trendChartWidth } = useElementSize()
  const currentCluster = cluster ?? EMPTY_CLUSTER
  const currentTidb = tidb ?? EMPTY_TIDB
  const currentSource = cluster ?? tidb
  const currentComputed = currentSource?.computed ?? EMPTY_COMPUTED
  const isPremiumSource = !!tidb
  const [highlightedKey, setHighlightedKey] = useState<string>()
  const [metric, setMetric] = useState<StatementMetricKey>(() => getDefaultStatementMetric(currentComputed))
  const [trendSlice, setTrendSlice] = useState<StatementSummaryDimension>('digest')

  useEffect(() => {
    document.title = `${config.PAGE_TITLE_PREFIX}Diagnosis - Statement Insight`
  }, [])

  const queryTimeRangeValue = useMemo(() => toTimeRangeValue(timeRange), [timeRange])
  const filteredKinds = useMemo(() => uniqueStrings(kinds), [kinds])
  const filteredDbs = useMemo(() => uniqueStrings(dbs), [dbs])
  const filteredSampleUsers = useMemo(() => uniqueStrings(sampleUsers), [sampleUsers])
  const filteredTableNames = useMemo(() => normalizeTableNames(tableNames), [tableNames])
  const tableFilterParams = useMemo(
    () => (filteredTableNames.length ? { field: 'table_names', values: filteredTableNames } : {}),
    [filteredTableNames]
  )
  const statementListParams = useMemo(
    () => ({
      begin_time: queryTimeRangeValue[0],
      end_time: queryTimeRangeValue[1],
      schemas: filteredDbs.length ? filteredDbs : undefined,
      stmt_types: filteredKinds.length ? filteredKinds : undefined,
      sample_user: filteredSampleUsers[0] || undefined,
      text: search || undefined,
      fields: STATEMENT_V2_FIELDS,
      ...tableFilterParams
    }),
    [filteredDbs, filteredKinds, filteredSampleUsers, queryTimeRangeValue, search, tableFilterParams]
  )
  const statementListClusterQuery = useGetStatementsListForCluster(
    orgId,
    activeProjectId,
    currentCluster,
    statementListParams,
    {
      query: {
        enabled:
          !isPremiumSource &&
          !!orgId &&
          !!activeProjectId &&
          !!currentCluster.id &&
          !currentComputed.creating &&
          !currentComputed.restoring,
        refetchOnWindowFocus: false,
        keepPreviousData: true
      }
    }
  )
  const statementListNextGenQuery = useGetStatementsList(orgId, currentTidb, statementListParams, {
    query: {
      enabled:
        isPremiumSource && !!orgId && !!currentTidb.tidbId && !currentComputed.creating && !currentComputed.restoring,
      refetchOnWindowFocus: false,
      keepPreviousData: true
    }
  })
  const statementListQuery = isPremiumSource ? statementListNextGenQuery : statementListClusterQuery

  const loading = statementListQuery.isLoading || statementListQuery.isFetching
  const metricOptions = useMemo(() => getStatementMetricOptions(currentComputed), [currentComputed])
  const rawData = useMemo(() => getStatementListRows(statementListQuery.data), [statementListQuery.data])

  useEffect(() => {
    if (!metricOptions.some((option) => option.value === metric)) {
      setMetric(getDefaultStatementMetric(currentComputed))
    }
  }, [currentComputed, metric, metricOptions])

  const tableData = useMemo(() => aggregateStatementsForTable(rawData), [rawData])
  const summaryStepSeconds = useMemo(
    () => getStatementSummaryStepSeconds(queryTimeRangeValue[1] - queryTimeRangeValue[0], trendChartWidth),
    [queryTimeRangeValue, trendChartWidth]
  )
  const remoteClusterQueryEnabled =
    !!orgId &&
    !!activeProjectId &&
    !!currentCluster.id &&
    !currentComputed.creating &&
    !currentComputed.restoring &&
    !isPremiumSource
  const remoteNextGenQueryEnabled =
    !!orgId && !!currentTidb.tidbId && !currentComputed.creating && !currentComputed.restoring && isPremiumSource
  const fieldValuesRangeKey = `${queryTimeRangeValue[0]}:${queryTimeRangeValue[1]}`
  const [openedFieldValues, setOpenedFieldValues] = useState<Partial<Record<StatementFieldValuesField, string>>>({})
  const markFieldValuesOpened = useCallback(
    (field: StatementFieldValuesField) => {
      setOpenedFieldValues((prev) => {
        if (prev[field] === fieldValuesRangeKey) {
          return prev
        }

        return {
          ...prev,
          [field]: fieldValuesRangeKey
        }
      })
    },
    [fieldValuesRangeKey]
  )
  const stmtKindFieldValues = useStatementFieldValues({
    orgId,
    activeProjectId,
    currentCluster,
    currentTidb,
    isPremiumSource,
    clusterEnabled: remoteClusterQueryEnabled,
    nextGenEnabled: remoteNextGenQueryEnabled,
    beginTime: queryTimeRangeValue[0],
    endTime: queryTimeRangeValue[1],
    field: 'stmt_types',
    enabled: openedFieldValues.stmt_types === fieldValuesRangeKey
  })
  const dbUserFieldValues = useStatementFieldValues({
    orgId,
    activeProjectId,
    currentCluster,
    currentTidb,
    isPremiumSource,
    clusterEnabled: remoteClusterQueryEnabled,
    nextGenEnabled: remoteNextGenQueryEnabled,
    beginTime: queryTimeRangeValue[0],
    endTime: queryTimeRangeValue[1],
    field: 'sample_user',
    enabled: openedFieldValues.sample_user === fieldValuesRangeKey
  })
  const dbFieldValues = useStatementFieldValues({
    orgId,
    activeProjectId,
    currentCluster,
    currentTidb,
    isPremiumSource,
    clusterEnabled: remoteClusterQueryEnabled,
    nextGenEnabled: remoteNextGenQueryEnabled,
    beginTime: queryTimeRangeValue[0],
    endTime: queryTimeRangeValue[1],
    field: 'schema_name',
    enabled: openedFieldValues.schema_name === fieldValuesRangeKey
  })
  const tableFieldValues = useStatementFieldValues({
    orgId,
    activeProjectId,
    currentCluster,
    currentTidb,
    isPremiumSource,
    clusterEnabled: remoteClusterQueryEnabled,
    nextGenEnabled: remoteNextGenQueryEnabled,
    beginTime: queryTimeRangeValue[0],
    endTime: queryTimeRangeValue[1],
    field: 'table_names',
    enabled: openedFieldValues.table_names === fieldValuesRangeKey
  })
  const statementSummaryDimension = trendSlice
  const statementSummaryParams = useMemo(
    () => ({
      begin_time: queryTimeRangeValue[0],
      end_time: queryTimeRangeValue[1],
      schemas: filteredDbs.length ? filteredDbs : undefined,
      stmt_types: filteredKinds.length ? filteredKinds : undefined,
      sample_user: filteredSampleUsers[0] || undefined,
      text: search || undefined,
      top: '10',
      order_by: metric,
      step: summaryStepSeconds,
      dimension: statementSummaryDimension,
      ...tableFilterParams
    }),
    [
      filteredDbs,
      filteredKinds,
      filteredSampleUsers,
      metric,
      queryTimeRangeValue,
      search,
      statementSummaryDimension,
      summaryStepSeconds,
      tableFilterParams
    ]
  )
  const statementsSummaryClusterQuery = useGetStatementsSummaryForCluster(
    orgId,
    activeProjectId,
    currentCluster,
    statementSummaryParams,
    {
      query: {
        enabled: remoteClusterQueryEnabled,
        refetchOnWindowFocus: false,
        keepPreviousData: true
      }
    }
  )
  const statementsSummaryNextGenQuery = useGetStatementsSummary(orgId, currentTidb, statementSummaryParams, {
    query: {
      enabled: remoteNextGenQueryEnabled,
      refetchOnWindowFocus: false,
      keepPreviousData: true
    }
  })
  const statementsSummaryQuery = isPremiumSource ? statementsSummaryNextGenQuery : statementsSummaryClusterQuery
  const topstatsBaseParams = useMemo(
    () => ({
      begin_time: queryTimeRangeValue[0],
      end_time: queryTimeRangeValue[1],
      schemas: filteredDbs.length ? filteredDbs : undefined,
      stmt_types: filteredKinds.length ? filteredKinds : undefined,
      sample_user: filteredSampleUsers[0] || undefined,
      text: search || undefined,
      top: '1000',
      order_by: metric,
      ...tableFilterParams
    }),
    [filteredDbs, filteredKinds, filteredSampleUsers, metric, queryTimeRangeValue, search, tableFilterParams]
  )
  const statementTopUsersClusterQuery = useGetStatementsTopstatsForCluster(
    orgId,
    activeProjectId,
    currentCluster,
    { ...topstatsBaseParams, dimension: 'user' },
    {
      query: {
        enabled: remoteClusterQueryEnabled,
        refetchOnWindowFocus: false,
        keepPreviousData: true
      }
    }
  )
  const statementTopUsersNextGenQuery = useGetStatementsTopstats(
    orgId,
    currentTidb,
    { ...topstatsBaseParams, dimension: 'user' },
    {
      query: {
        enabled: remoteNextGenQueryEnabled,
        refetchOnWindowFocus: false,
        keepPreviousData: true
      }
    }
  )
  const statementTopUsersQuery = isPremiumSource ? statementTopUsersNextGenQuery : statementTopUsersClusterQuery
  const statementTopTypesClusterQuery = useGetStatementsTopstatsForCluster(
    orgId,
    activeProjectId,
    currentCluster,
    { ...topstatsBaseParams, dimension: 'sqltypes' },
    {
      query: {
        enabled: remoteClusterQueryEnabled,
        refetchOnWindowFocus: false,
        keepPreviousData: true
      }
    }
  )
  const statementTopTypesNextGenQuery = useGetStatementsTopstats(
    orgId,
    currentTidb,
    { ...topstatsBaseParams, dimension: 'sqltypes' },
    {
      query: {
        enabled: remoteNextGenQueryEnabled,
        refetchOnWindowFocus: false,
        keepPreviousData: true
      }
    }
  )
  const statementTopTypesQuery = isPremiumSource ? statementTopTypesNextGenQuery : statementTopTypesClusterQuery
  const statementTopSqlsClusterQuery = useGetStatementsTopstatsForCluster(
    orgId,
    activeProjectId,
    currentCluster,
    { ...topstatsBaseParams, dimension: 'digest' },
    {
      query: {
        enabled: remoteClusterQueryEnabled,
        refetchOnWindowFocus: false,
        keepPreviousData: true
      }
    }
  )
  const statementTopSqlsNextGenQuery = useGetStatementsTopstats(
    orgId,
    currentTidb,
    { ...topstatsBaseParams, dimension: 'digest' },
    {
      query: {
        enabled: remoteNextGenQueryEnabled,
        refetchOnWindowFocus: false,
        keepPreviousData: true
      }
    }
  )
  const statementTopSqlsQuery = isPremiumSource ? statementTopSqlsNextGenQuery : statementTopSqlsClusterQuery
  const statementTopDbsClusterQuery = useGetStatementsTopstatsForCluster(
    orgId,
    activeProjectId,
    currentCluster,
    { ...topstatsBaseParams, dimension: 'db' },
    {
      query: {
        enabled: remoteClusterQueryEnabled,
        refetchOnWindowFocus: false,
        keepPreviousData: true
      }
    }
  )
  const statementTopDbsNextGenQuery = useGetStatementsTopstats(
    orgId,
    currentTidb,
    { ...topstatsBaseParams, dimension: 'db' },
    {
      query: {
        enabled: remoteNextGenQueryEnabled,
        refetchOnWindowFocus: false,
        keepPreviousData: true
      }
    }
  )
  const statementTopDbsQuery = isPremiumSource ? statementTopDbsNextGenQuery : statementTopDbsClusterQuery
  const statementTopTablesClusterQuery = useGetStatementsTopstatsForCluster(
    orgId,
    activeProjectId,
    currentCluster,
    { ...topstatsBaseParams, dimension: 'table' },
    {
      query: {
        enabled: remoteClusterQueryEnabled,
        refetchOnWindowFocus: false,
        keepPreviousData: true
      }
    }
  )
  const statementTopTablesNextGenQuery = useGetStatementsTopstats(
    orgId,
    currentTidb,
    { ...topstatsBaseParams, dimension: 'table' },
    {
      query: {
        enabled: remoteNextGenQueryEnabled,
        refetchOnWindowFocus: false,
        keepPreviousData: true
      }
    }
  )
  const statementTopTablesQuery = isPremiumSource ? statementTopTablesNextGenQuery : statementTopTablesClusterQuery
  const stripUserPrefix = currentComputed.isEssential
  const remoteContributorSummaries = useMemo(
    () => ({
      users: buildStatementContributorSummaryFromTopstats(
        metric,
        'user',
        statementTopUsersQuery.data?.data || [],
        stripUserPrefix
      ),
      types: buildStatementContributorSummaryFromTopstats(metric, 'sqltypes', statementTopTypesQuery.data?.data || []),
      sqls: buildStatementContributorSummaryFromTopstats(metric, 'digest', statementTopSqlsQuery.data?.data || []),
      dbs: buildStatementContributorSummaryFromTopstats(metric, 'db', statementTopDbsQuery.data?.data || []),
      tables: buildStatementContributorSummaryFromTopstats(metric, 'table', statementTopTablesQuery.data?.data || [])
    }),
    [
      metric,
      statementTopDbsQuery.data,
      statementTopSqlsQuery.data,
      statementTopTablesQuery.data,
      statementTopTypesQuery.data,
      statementTopUsersQuery.data,
      stripUserPrefix
    ]
  )
  const normalizedRemoteSummary = useMemo(
    () => normalizeStatementSummaryResponse(statementsSummaryQuery.data?.data as unknown),
    [statementsSummaryQuery.data]
  )
  const remoteTrendSeries = useMemo(
    () =>
      buildStatementTrendSeriesFromSummary(
        normalizedRemoteSummary.items,
        queryTimeRangeValue,
        summaryStepSeconds,
        statementSummaryDimension,
        stripUserPrefix
      ),
    [normalizedRemoteSummary.items, queryTimeRangeValue, statementSummaryDimension, stripUserPrefix, summaryStepSeconds]
  )
  const contributorSummaries = remoteContributorSummaries
  const trendSeries = remoteTrendSeries
  const trendStepSeconds = summaryStepSeconds
  const trendValueFormatter = useMemo(() => (value: number) => formatStatementMetricValue(metric, value), [metric])
  const trendLoading = statementsSummaryQuery.isFetching
  const contributorLoading =
    statementTopUsersQuery.isFetching ||
    statementTopTypesQuery.isFetching ||
    statementTopSqlsQuery.isFetching ||
    statementTopDbsQuery.isFetching ||
    statementTopTablesQuery.isFetching
  const filterLoading = loading || contributorLoading
  const tableLoading = loading
  const visibleTableData = tableData

  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(
    () =>
      trendSeries.reduce<Record<string, string>>((map, series, index) => {
        map[series.key] = trendColorPalette[index % trendColorPalette.length]
        return map
      }, {}),
    [trendColorPalette, trendSeries]
  )
  const coloredTrendSeries = useMemo(
    () =>
      trendSeries.map((series, index) => ({
        ...series,
        color: seriesColorMap[series.key] || trendColorPalette[index % trendColorPalette.length]
      })),
    [seriesColorMap, trendColorPalette, trendSeries]
  )
  const visibleTrendSeries = trendLoading ? [] : coloredTrendSeries
  const tableSeriesColorMap = useMemo(
    () =>
      tableData.reduce<Record<string, string>>(
        (map, row, index) => {
          const color = trendColorPalette[index % trendColorPalette.length]
          const recordKey = getStatementRecordKey(row)

          map[recordKey] ||= color
          if (row.digest) {
            map[row.digest] ||= color
          }

          return map
        },
        { ...seriesColorMap }
      ),
    [seriesColorMap, tableData, trendColorPalette]
  )

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

    eventTracking(`${FEATURE_NAME_V2} Trend Brush Changed`)
  }

  const handleTableHover = (rowKey: string) => {
    setHighlightedKey(rowKey)
    onLegendItemOver(trendChartRef.current, rowKey)
  }

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

  const handleRowClick = (row: any) => {
    const detailPath =
      detailPathBase ||
      (cluster
        ? `/clusters/${cluster.id}/diagnosis/sql-statement-v2/detail`
        : `/tidbs/${tidb?.tidbId || ''}/diagnosis/sql-statement-v2/detail`)

    history.push(
      `${detailPath}?${new URLSearchParams({
        digest: row.digest ?? '',
        schema_name: row.schema_name ?? '',
        begin_time: String(queryTimeRangeValue[0]),
        end_time: String(queryTimeRangeValue[1]),
        source: 'statement-v2'
      })}`,
      {
        historyBack: true,
        detailFromHref: window.location.pathname + window.location.search
      }
    )
    eventTracking(`${FEATURE_NAME_V2} List Table Row Clicked`)
  }

  if (currentSource && isClusterInvalid(currentSource)) {
    return (
      <Stack>
        <StatementFilters
          isLoading={false}
          stmtKindOptions={stmtKindFieldValues.data}
          dbUserOptions={dbUserFieldValues.data}
          dbOptions={dbFieldValues.data}
          tableOptions={tableFieldValues.data}
          stmtKindsLoading={stmtKindFieldValues.isFetching}
          dbUsersLoading={dbUserFieldValues.isFetching}
          dbsLoading={dbFieldValues.isFetching}
          tablesLoading={tableFieldValues.isFetching}
          onStmtKindsOpen={() => markFieldValuesOpened('stmt_types')}
          onDbUsersOpen={() => markFieldValuesOpened('sample_user')}
          onDbsOpen={() => markFieldValuesOpened('schema_name')}
          onTablesOpen={() => markFieldValuesOpened('table_names')}
          computed={currentComputed}
        />
        <Card shadow="none" h="calc(100vh - 262px)">
          {cluster ? (
            <PausedStatus
              cluster={cluster}
              featureName="Statement Insight"
              featureDesc="Statement Insight enables side-by-side comparison with the current Statement page."
            />
          ) : (
            <Stack align="center" justify="center" h="100%">
              <Typography variant="body-lg" c="carbon.7" ta="center">
                Statement Insight is unavailable while this cluster is {String(tidb?.state || '').toLowerCase()}.
              </Typography>
            </Stack>
          )}
        </Card>
      </Stack>
    )
  }

  return (
    <Stack mx={-24} gap="md" data-testid="statement-v2-page">
      {(currentComputed.isServerless || isPremiumSource) && (
        <Alert ml={24} mb={8} color="peacock">
          <Typography variant="body-lg" pr={8}>
            Data collection started when Statement Insight was enabled. Your available history grows day by day,
            currently no historical backfill.
          </Typography>
        </Alert>
      )}

      <Flex px={24} justify="flex-start" wrap="wrap" gap="md">
        <StatementFilters
          isLoading={filterLoading}
          stmtKindOptions={stmtKindFieldValues.data}
          dbUserOptions={dbUserFieldValues.data}
          dbOptions={dbFieldValues.data}
          tableOptions={tableFieldValues.data}
          stmtKindsLoading={stmtKindFieldValues.isFetching}
          dbUsersLoading={dbUserFieldValues.isFetching}
          dbsLoading={dbFieldValues.isFetching}
          tablesLoading={tableFieldValues.isFetching}
          onStmtKindsOpen={() => markFieldValuesOpened('stmt_types')}
          onDbUsersOpen={() => markFieldValuesOpened('sample_user')}
          onDbsOpen={() => markFieldValuesOpened('schema_name')}
          onTablesOpen={() => markFieldValuesOpened('table_names')}
          computed={currentComputed}
        />
      </Flex>

      {statementListQuery.isFetched && <HeroComponent />}

      <Card withBorder mx={24} p="md" data-testid="statement-v2-contributors-card">
        <Stack gap="lg">
          <Group justify="space-between" align="center">
            <Typography variant="title-lg">Top Contributors</Typography>
            <Group gap="xs" align="center">
              <Typography variant="label-md" c="carbon.7">
                Measured by
              </Typography>
              <Select
                w={160}
                size="sm"
                value={metric}
                data={metricOptions}
                disabled={filterLoading}
                onChange={(value) => {
                  if (!value) {
                    return
                  }
                  setMetric(value as StatementMetricKey)
                  eventTracking(`${FEATURE_NAME_V2} Metric Changed`, { metric: value })
                }}
              />
            </Group>
          </Group>

          <Grid gutter="lg">
            <Grid.Col span={{ base: 12, lg: 3 }}>
              <ContributorCard
                title="DB Users"
                total={contributorSummaries.users.totalCount}
                metric={metric}
                totalValue={contributorSummaries.users.totalValue}
                items={contributorSummaries.users.items}
                loading={contributorLoading}
                testId="statement-v2-users-card"
              />
            </Grid.Col>
            <Grid.Col span={{ base: 12, lg: 3 }}>
              <ContributorCard
                title="SQL Types"
                total={contributorSummaries.types.totalCount}
                metric={metric}
                totalValue={contributorSummaries.types.totalValue}
                items={contributorSummaries.types.items}
                loading={contributorLoading}
                testId="statement-v2-types-card"
              />
            </Grid.Col>
            <Grid.Col span={{ base: 12, lg: 6 }}>
              <ContributorCard
                title="SQL Templates"
                total={contributorSummaries.sqls.totalCount}
                metric={metric}
                totalValue={contributorSummaries.sqls.totalValue}
                items={contributorSummaries.sqls.items}
                loading={contributorLoading}
                testId="statement-v2-sql-card"
                variant="sql"
              />
            </Grid.Col>
          </Grid>

          <Grid gutter="lg">
            <Grid.Col span={{ base: 12, lg: 3 }}>
              <ContributorCard
                title="DBs"
                total={contributorSummaries.dbs.totalCount}
                metric={metric}
                totalValue={contributorSummaries.dbs.totalValue}
                items={contributorSummaries.dbs.items}
                loading={contributorLoading}
                testId="statement-v2-dbs-card"
              />
            </Grid.Col>
            <Grid.Col span={{ base: 12, lg: 3 }}>
              <ContributorCard
                title="Tables"
                total={contributorSummaries.tables.totalCount}
                metric={metric}
                totalValue={contributorSummaries.tables.totalValue}
                items={contributorSummaries.tables.items}
                loading={contributorLoading}
                testId="statement-v2-tables-card"
              />
            </Grid.Col>
          </Grid>

          <Box
            pt="lg"
            sx={{ borderTop: '1px solid var(--mantine-color-carbon-3)' }}
            data-testid="statement-v2-trend-card"
          >
            <Stack gap="lg">
              <Group justify="space-between" align="center">
                <Typography variant="title-lg">Resource Usage Over Time</Typography>
                <Group gap="xs" align="center">
                  <Typography variant="label-md" c="carbon.7">
                    Sliced by
                  </Typography>
                  <Select
                    w={120}
                    size="sm"
                    value={trendSlice}
                    onChange={(value) => {
                      if (!value) {
                        return
                      }

                      setTrendSlice(value as StatementSummaryDimension)
                      eventTracking(`${FEATURE_NAME_V2} Trend Slice Changed`, { slice: value })
                    }}
                    data={[
                      { label: 'SQL', value: 'digest' },
                      { label: 'User', value: 'user' },
                      { label: 'SQL Type', value: 'sqltypes' },
                      { label: 'DB', value: 'db' },
                      { label: 'Table', value: 'table' }
                    ]}
                  />
                </Group>
              </Group>

              <Box ref={trendChartSizeRef} h={320} w="100%" sx={{ minWidth: 0, display: 'flex' }}>
                <TrendChart
                  ref={trendChartRef}
                  data={visibleTrendSeries}
                  loading={trendLoading}
                  timeRangeValue={queryTimeRangeValue}
                  stepSeconds={trendStepSeconds}
                  valueFormatter={trendValueFormatter}
                  highlightedKey={highlightedKey}
                  onBrushEnd={handleBrushEnd}
                />
              </Box>
            </Stack>
          </Box>
        </Stack>
      </Card>

      <ListTable
        data={visibleTableData}
        loading={tableLoading}
        computed={currentComputed}
        sortBy={sortRules}
        onSortChange={setSortRules}
        seriesColorMap={tableSeriesColorMap}
        highlightedKey={highlightedKey}
        onRowHover={handleTableHover}
        onRowLeave={handleTableLeave}
        onRowClick={handleRowClick}
      />
    </Stack>
  )
}

export default React.memo(
  StatementV2Page,
  (prevProps, nextProps) =>
    (prevProps.cluster?.id ?? prevProps.tidb?.tidbId) === (nextProps.cluster?.id ?? nextProps.tidb?.tidbId)
)
