import * as Sentry from '@sentry/react'
import { Box, Group, Stack, Typography } from '@tidbcloud/uikit'
import { useTimeout } from '@tidbcloud/uikit/hooks'
import { IconLightbulb02 } from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'
import { useEffect, useState } from 'react'
import { Link, Redirect } from 'react-router-dom'

import { PageLoader } from 'dbaas/components/Placeholder'
import { filterUserProfileProjects } from 'dbaas/features/Project'
import { CentralAuth0AuditLogReqOperation, updateAuth0AuditLog } from 'dbaas/services'
import { useGetUserProfileV2 } from 'dbaas/services/account'
import { useServerlessServiceGetCluster } from 'dbaas/services/api-clients/v2023/serverless/v1beta1'
import { Commonv1beta1ClusterState } from 'dbaas/services/api-clients/v2023/serverless/v1beta1/interface'
import { ram } from 'dbaas/stores/ram'
import useStores from 'dbaas/stores/useStores'
import { eventTracking, identifyUser } from 'dbaas/utils/tracking'
import TiDBLoadingSVG from 'media/loader/tidb-loading.svg?react'

import { markServerlessOnboardingDone, pickClusterInfo } from './helpers'

// Transition duration
const MIN_TIMEOUT_SEC = 6 * 1000
const MAX_TIMEOUT_SEC = 24 * 1000

export const ServerlessOnboarding = observer(() => {
  const {
    actions: { updateLastVisitLocation, updateUserProfileModel, fetchTenantPlanInfo, fetchWhiteList }
  } = useStores()

  // Minimum transition duration for creating cluster
  const [minTimeEnd, setMinTimeEnd] = useState(false)
  const minTimer = useTimeout(() => setMinTimeEnd(true), MIN_TIMEOUT_SEC)
  // Maximal transition duration for creating cluster
  const [maxTimeEnd, setMaxTimeEnd] = useState(false)
  const maxTimer = useTimeout(() => setMaxTimeEnd(true), MAX_TIMEOUT_SEC)

  const [userLoaded, setUserLoaded] = useState(false)
  const userQuery = useGetUserProfileV2({
    query: {
      refetchOnWindowFocus: false,
      select: (data) => ({
        ...data,
        projects: filterUserProfileProjects(data.projects)
      }),
      onSuccess: (data) => {
        const { valid } = pickClusterInfo(data)

        /**
         * If the cluster info is valid, we can set
         * `userLoaded` to true and start the duration timer.
         */
        if (valid && !userLoaded) {
          setUserLoaded(true)
          minTimer.start()
          maxTimer.start()
        }
      }
    }
  })

  const params = new URLSearchParams(window.location.search)

  useEffect(() => {
    const data = userQuery.data

    if (userLoaded && data) {
      const { orgId, projectId } = pickClusterInfo(data)
      // Sync data to the global store
      updateLastVisitLocation({ orgId, projectId })
      updateUserProfileModel(data, orgId)

      // Mark onboarding flag to `done`
      markServerlessOnboardingDone(data.email)

      /**
       * The following steps are the same as those in `App.tsx`
       */
      Sentry.setUser({
        id: data.user_id,
        email: data.email
      })

      identifyUser(
        {
          ...data,
          id: data.user_id
        },
        {
          third_party_account_provider: data.orgs?.[0]?.third_party_account_provider || ''
        }
      )

      if (ram.get('reportLogin')) {
        eventTracking('Login')
        updateAuth0AuditLog(
          {
            operation: CentralAuth0AuditLogReqOperation.SIGNIN,
            is_success: true,
            failure_info: '',
            org_id: orgId || ''
          },
          { isHandleErr: true }
        )
        ram.clear('reportLogin')
      }
    }
  }, [updateLastVisitLocation, updateUserProfileModel, userLoaded, userQuery.data])

  useEffect(() => {
    if (!userLoaded) {
      return
    }

    /**
     * The following actions are the same as those in `App.tsx`
     */
    fetchTenantPlanInfo()
    fetchWhiteList()
  }, [fetchTenantPlanInfo, fetchWhiteList, userLoaded])

  const { orgId, projectId, clusterId, valid } = pickClusterInfo(userQuery.data)
  const clusterQuery = useServerlessServiceGetCluster(
    clusterId,
    {
      view: 'BASIC',
      orgId,
      projectId
    },
    {
      query: {
        enabled: valid,
        refetchOnWindowFocus: false,
        refetchInterval: (data) => {
          return data?.state === Commonv1beta1ClusterState.CREATING ? 3 * 1000 : false
        }
      }
    }
  )
  const successful =
    userQuery.isSuccess && clusterQuery.isSuccess && clusterQuery.data.state === Commonv1beta1ClusterState.ACTIVE
  const clusterException = clusterQuery.isSuccess && clusterQuery.data.state !== Commonv1beta1ClusterState.ACTIVE

  if (minTimeEnd && successful) {
    let url = `/clusters/${clusterId}/overview`
    if (params.has('guideAction')) {
      url = `${url}?guideAction=${params.get('guideAction')}&targetId=${clusterId}`
    }
    return <Redirect to={url} />
  }

  if ((minTimeEnd && clusterQuery.isError) || (maxTimeEnd && clusterException)) {
    return <Redirect to="/clusters" />
  }

  // FIXME: The current fallback route is the root
  if (userQuery.isError) {
    return <Redirect to="/" />
  }

  if (userQuery.isLoading) {
    return <PageLoader />
  }

  return (
    <Stack align="center" justify="center" gap="xl" h="100vh">
      <TiDBLoadingSVG width={70} height={80} />
      <Stack align="center" gap="sm">
        <Typography variant="headline-lg">Working on creating the first cluster in your org...</Typography>
        <Typography variant="body-lg">
          You can also go back to{' '}
          <Link to="/clusters" onClick={() => markServerlessOnboardingDone()}>
            clusters
          </Link>{' '}
          during the cluster creation.
        </Typography>
      </Stack>
      <Group align="flex-start" mt="xl">
        <IconLightbulb02 size={24} />
        <Box>
          <Typography variant="label-lg">You can create up to 5 clusters for free tier account.</Typography>
          <Typography variant="label-lg">And free up to 50M RUs per month and 5GiB storage per cluster.</Typography>
        </Box>
      </Group>
    </Stack>
  )
})

export default ServerlessOnboarding
