import { Stack } from '@tidbcloud/uikit'
import React, { useEffect, useMemo } from 'react'
import { useQuery } from 'react-query'
import { useHistory } from 'react-router-dom'

import config from 'config'
import { HeroComponent, isHeroQueryReady } from 'dbaas/components/Measurement'
import { SharedCluster } from 'dbaas/features/ClusterManagement/cluster'
import { ClusterPageShell } from 'dbaas/screens/ClusterV2/components'
import useStores from 'dbaas/stores/useStores'
import { eventTracking } from 'dbaas/utils/tracking'

import { StatementProvider, useStatementContext } from '../utils/context'
import { getStatementContext } from '../utils/context-impl'
import { StatementModel } from '../utils/type'

import { PlanDetail } from './PlanDetail'
import { PlansList } from './plans-list/PlansList'
import { StmtSummary } from './StmtSummary'
import { useStatementDetailUrlState } from './url-state'

export const StatementDetail: React.FC<React.PropsWithChildren<{ hero?: boolean }>> = ({ hero = false }) => {
  useEffect(() => {
    document.title = `${config.PAGE_TITLE_PREFIX}Statement Detail`
  }, [])
  const ctx = useStatementContext()
  const { digest, schema_name, begin_time, end_time, plans, setPlans } = useStatementDetailUrlState()
  const selectedPlans = useMemo(() => plans.slice(0, 1), [plans])
  const selectedPlanDigest = selectedPlans[0]

  const {
    data: stmtPlans,
    isLoading: fetchingPlans,
    isFetched,
    isError
  } = useQuery(
    ['statement_detail', 'plans', ctx.cfg.clusterId, digest, schema_name, begin_time, end_time],
    () => ctx.ds.getStmtPlans({ digest, schema_name, begin_time, end_time }),
    {
      refetchOnWindowFocus: false
    }
  )
  const stmtSummary = stmtPlans?.[0]
  useEffect(() => {
    if (!stmtPlans?.length) {
      return
    }

    const availablePlans = stmtPlans.map((plan) => plan.plan_digest).filter((digest): digest is string => !!digest)
    const currentPlan = selectedPlans[0]
    const selectedPlan = currentPlan && availablePlans.includes(currentPlan) ? currentPlan : availablePlans[0]
    if (selectedPlan && (plans.length !== 1 || plans[0] !== selectedPlan)) {
      setPlans([selectedPlan])
    }
  }, [plans, selectedPlans, setPlans, stmtPlans])

  const { data: planDetailResult, isLoading: fetchingPlanDetail } = useQuery<{
    planDigest: string
    detail: StatementModel
  }>(
    ['statement_detail', 'detail', ctx.cfg.clusterId, digest, schema_name, begin_time, end_time, selectedPlans],
    async ({ signal }) => ({
      planDigest: selectedPlanDigest!,
      detail: await ctx.ds.getStmtPlanDetail(
        { digest, schema_name, begin_time, end_time, plans: selectedPlans },
        signal
      )
    }),
    {
      enabled: selectedPlans.length > 0,
      refetchOnWindowFocus: false
    }
  )
  const stmtPlanDetail =
    planDetailResult && planDetailResult.planDigest === selectedPlanDigest ? planDetailResult.detail : undefined
  const planDetailLoading = fetchingPlanDetail || (!!planDetailResult && !stmtPlanDetail)

  const loading = fetchingPlans

  return (
    <Stack>
      {hero && <HeroComponent ready={isHeroQueryReady({ isFetched, isError })} />}
      <StmtSummary stmt={stmtSummary} plansCount={stmtPlans?.length ?? 0} loading={loading} />

      {!!stmtPlans?.length && <PlansList data={stmtPlans} />}

      {selectedPlans.length > 0 && (
        <PlanDetail key={selectedPlanDigest} planDetail={stmtPlanDetail} loading={planDetailLoading} />
      )}
    </Stack>
  )
}

/////////////////////////////////////////

interface StatementDetailPageProps {
  cluster: SharedCluster
}

const StatementDetailContent: React.FC = () => {
  const ctx = useStatementContext()

  return (
    <ClusterPageShell
      title="Statement Detail"
      headerProps={{
        withBack: true,
        onBackClick() {
          ctx.event.backFromDetail()
          eventTracking('Statement Detail Back Button Clicked')
        }
      }}
    >
      <StatementDetail />
    </ClusterPageShell>
  )
}

const StatementDetailPage: React.FC<React.PropsWithChildren<StatementDetailPageProps>> = ({ cluster }) => {
  const {
    store: {
      tenantData: { id: orgId },
      activeProjectId
    }
  } = useStores()
  const history = useHistory()

  return (
    <StatementProvider
      value={getStatementContext(
        {
          orgId,
          projectId: activeProjectId,
          clusterId: cluster.id,
          clusterProvider: cluster.provider,
          clusterRegion: cluster.region,
          computed: cluster.computed
        },
        history
      )}
    >
      <StatementDetailContent />
    </StatementProvider>
  )
}

// use React.memo to prevent re-rendering when the cluster is updating periodically
export default React.memo(StatementDetailPage, (prevProps, nextProps) => prevProps.cluster.id === nextProps.cluster.id)
