import useUrlState from '@ahooksjs/use-url-state'
import { Card, Group, Skeleton, Stack, Tabs, Title } from '@tidbcloud/uikit'
import { CodeBlock } from '@tidbcloud/uikit/biz'
import { observer } from 'mobx-react'
import { useMemo } from 'react'
import { JSONTree } from 'react-json-tree'
import { useHistory, useLocation } from 'react-router-dom'

import { HeroComponent, isHeroQueryReady } from 'dbaas/components/Measurement'
import { useSharedTiDBContext } from 'dbaas/screens/NextGen/tidb-mgmt-container/shared/tidb-context'
import { TiDBPageShell } from 'dbaas/screens/NextGen/tidb-mgmt-container/shared/TiDBPageShell'
import { SlowquerySlowLogRespItem } from 'dbaas/services/ngm/interface'
import { useGetSlowQueryDetail } from 'dbaas/services/useO11YQuery'
import useStores from 'dbaas/stores/useStores'
import { eventTracking } from 'dbaas/utils/tracking'

import { formatSql } from '../../shared/diagnosis/HighlightSQL'

import DetailBasic from './DetailBasic'
import DetailCoprocessor from './DetailCop'
import DetailTime from './DetailTime'
import DetailTxn from './DetailTxn'

type SlowQueryDetailData = SlowquerySlowLogRespItem & {
  binary_plan_text?: string
}

const SlowQueryDetail = observer(() => {
  const tidb = useSharedTiDBContext()
  const {
    store: {
      tenantData: { id: orgId }
    }
  } = useStores()
  const history = useHistory()
  const location = useLocation<{ historyBack?: boolean }>()
  const [{ digest, connection_id, timestamp }] = useUrlState<{
    digest: string
    connection_id: string
    timestamp: string
  }>()
  const { data, isLoading, isFetched, isError } = useGetSlowQueryDetail(
    orgId,
    tidb,
    {
      digest,
      connect_id: connection_id,
      timestamp
    },
    {
      query: {
        refetchOnWindowFocus: false
      }
    }
  )
  const detailData = data as SlowQueryDetailData | undefined

  return (
    <TiDBPageShell
      title="Slow Query Detail"
      headerProps={{
        withBack: true,
        onBackClick() {
          if (!!location.state?.historyBack) {
            history.goBack()
          } else {
            history.replace(`/tidbs/${tidb.tidbId}/diagnosis/slow-query`)
          }
          eventTracking('Slow Query Detail Back Button Clicked')
        }
      }}
    >
      <HeroComponent ready={isHeroQueryReady({ isFetched, isError })} />
      {!detailData || isLoading ? (
        <Group gap="xs">
          <Skeleton height={10} />
          <Skeleton height={10} />
          <Skeleton height={10} width="70%" />
        </Group>
      ) : (
        <Stack gap="xl">
          <QuerySegment data={detailData} />
          {(detailData.binary_plan_text || detailData.plan) && <PlanSegment data={detailData} />}
          <InfoSegment data={detailData} />
        </Stack>
      )}
    </TiDBPageShell>
  )
})

const QuerySegment: React.FC<React.PropsWithChildren<{ data: SlowQueryDetailData }>> = ({ data }) => {
  const formattedSQL = useMemo(() => formatSql(data.query), [data.query])
  const formattedPrevSQL = useMemo(() => formatSql(data.prev_stmt), [data.prev_stmt])

  return (
    <Card shadow="none" p="xl" data-testid="slowquery-detail-query">
      <Stack gap="xs">
        <Title order={5}>Query</Title>

        <CodeBlock
          language="sql"
          foldProps={{
            persistenceKey: 'dbaas.slowquery.detail.query',
            iconVisible: true,
            onIconClick: () => eventTracking('Slow Query Detail Expand Clicked', { type: 'query' })
          }}
          onCopyClick={() => eventTracking('Slow Query Detail Copy Clicked', { type: 'query' })}
        >
          {formattedSQL}
        </CodeBlock>

        {data.prev_stmt && (
          <>
            <Title order={5}>Previous Query</Title>

            <CodeBlock
              language="sql"
              foldProps={{
                persistenceKey: 'dbaas.slowquery.detail.previous-query',
                iconVisible: true,
                onIconClick: () => eventTracking('Slow Query Detail Expand Clicked', { type: 'previous-query' })
              }}
              onCopyClick={() => eventTracking('Slow Query Detail Copy Clicked', { type: 'previous-query' })}
            >
              {formattedPrevSQL}
            </CodeBlock>
          </>
        )}
      </Stack>
    </Card>
  )
}

const PlanSegment: React.FC<React.PropsWithChildren<{ data: SlowQueryDetailData }>> = ({ data }) => {
  return (
    <Card shadow="none" p="xl" data-testid="slowquery-detail-plan">
      <Stack gap="xs">
        <Title order={5}>Plan</Title>

        <CodeBlock
          codeRender={(content) => <pre>{content}</pre>}
          foldProps={{
            persistenceKey: 'dbaas.slowquery.detail.plan',
            iconVisible: true,
            onIconClick: () => eventTracking('Slow Query Detail Expand Clicked', { type: 'plan' })
          }}
          onCopyClick={() => eventTracking('Slow Query Detail Copy Clicked', { type: 'plan' })}
        >
          {data.binary_plan_text || data.plan || ''}
        </CodeBlock>
      </Stack>
    </Card>
  )
}

function WarningsJsonView({ data }: { data: object }) {
  return (
    <JSONTree
      data={data}
      shouldExpandNodeInitially={() => true}
      theme={{
        tree: ({ style }) => {
          return {
            style: {
              ...style,
              backgroundColor: 'transparent'
            }
          }
        }
      }}
    />
  )
}

const InfoSegment: React.FC<React.PropsWithChildren<{ data: SlowQueryDetailData }>> = ({ data }) => {
  const tabs = useMemo(() => {
    const _tabs = [
      {
        label: 'Basic',
        value: 'basic',
        component: <DetailBasic data={data} />
      },
      { label: 'Time', value: 'time', component: <DetailTime data={data} /> },
      {
        label: 'Coprocessor',
        value: 'copr',
        component: <DetailCoprocessor data={data} />
      },
      {
        label: 'Transaction',
        value: 'txn',
        component: <DetailTxn data={data} />
      }
    ]
    if (data.warnings) {
      let jsonData = {}
      if (typeof data.warnings === 'string') {
        jsonData = JSON.parse(data.warnings)
      } else if (typeof data.warnings === 'object') {
        jsonData = data.warnings
      }
      _tabs.push({
        label: 'Warnings',
        value: 'warnings',
        component: <WarningsJsonView data={jsonData} />
      })
    }
    return _tabs
  }, [data])

  return (
    <Card shadow="none" p="xl" data-testid="slowquery-detail-detailinfo">
      <Stack gap="xs">
        <Title order={5}>Detail</Title>

        <Tabs defaultValue={tabs[0].value}>
          <Stack gap="md">
            <Tabs.List>
              {tabs.map((tab) => (
                <Tabs.Tab
                  key={tab.value}
                  value={tab.value}
                  onClick={() => eventTracking('Slow Query Detail Tab Clicked', { value: tab.value })}
                >
                  {tab.label}
                </Tabs.Tab>
              ))}
            </Tabs.List>

            {tabs.map((tab) => (
              <Tabs.Panel key={tab.value} value={tab.value}>
                {tab.component}
              </Tabs.Panel>
            ))}
          </Stack>
        </Tabs>
      </Stack>
    </Card>
  )
}

export default SlowQueryDetail
