import { notifier } from '@tidbcloud/uikit'
import { Flex, ActionIcon, Loader } from '@tidbcloud/uikit'
import { IconPlus } from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'
import { useEffect, useState } from 'react'

import { useAccessCheck } from 'dbaas/contexts/access-control'
import { useFetchCreationDefaultName, useFetchProviders } from 'dbaas/features/ClusterManagement/common'
import { useCreateServerlessCluster } from 'dbaas/features/ClusterManagement/serverless'
import { CloudProviderConst } from 'dbaas/features/Project'
import { useIsClusterReady } from 'dbaas/screens/GettingStarted/helpers'
import { getErrorMessage } from 'dbaas/services/errorCodes'
import useStores from 'dbaas/stores/useStores'

interface ClusterCreationItemProps {
  onChange?: (args: { id: string; name: string }) => void
}

const CreateCluster = observer(({ onChange }: ClusterCreationItemProps) => {
  const [newCluster, setNewCluster] = useState<{ id: string; name: string } | undefined>()

  const {
    query: { refetch: fetchClusterName }
  } = useFetchCreationDefaultName()

  const {
    query: { data: { cloud_providers: providers = [] } = {} }
  } = useFetchProviders({ tier: 'serverless' })
  const availableProviders = providers.find((item) => item.name === CloudProviderConst.AWS)
  const provider = availableProviders ?? { name: '', regions: [] }
  const region = provider.regions.length ? provider.regions[0] : { name: '' }
  const {
    ready: clusterReady,
    error: queryError,
    deleted,
    remove,
    creating: clusterCreating
  } = useIsClusterReady(newCluster?.id || '', true)

  const {
    createCluster,
    isCreating: creationLoading,
    mutation: { error: creationError, reset: resetCreation }
  } = useCreateServerlessCluster({
    provider: provider.name,
    region: region.name
  })

  // detect whether the newly cluster is ready
  useEffect(() => {
    // if newly cluster is ready, need refresh
    if (clusterReady) {
      // if user switch back and return, we should not notice
      if (newCluster?.id) {
        notifier.success(`${newCluster.name || 'Cluster'} successfully created.`)
      }
    }
  }, [clusterReady, newCluster])

  useEffect(() => {
    if ((deleted || clusterReady) && !!newCluster?.id) {
      setNewCluster(undefined)
      remove()
    }
  }, [newCluster?.id, deleted, clusterReady])

  const handleCreateCluster = async () => {
    const { data } = await fetchClusterName()
    const clusterName = data?.name ?? ''

    setNewCluster({ id: '', name: clusterName })
    const { clusterId } = await createCluster({
      provider: provider.name,
      region: region.name,
      name: clusterName
    })
    if (clusterId) {
      onChange?.({ id: clusterId, name: clusterName })
      setNewCluster({ id: clusterId, name: clusterName })
    }
  }

  useEffect(() => {
    if (error) {
      notifier.error(error)
      resetCreation()
    }
  }, [queryError, creationError])

  const error =
    getErrorMessage(creationError) || getErrorMessage(queryError) || (deleted ? 'The cluster is deleted' : '')
  const isCreating = ((creationLoading || (!!newCluster?.id && !clusterReady)) && !error) || clusterCreating

  return (
    <Flex
      onClick={handleCreateCluster}
      align="center"
      sx={(theme) => ({
        '&:hover': {
          backgroundColor: theme.colors.carbon[3]
        },
        borderRadius: theme.defaultRadius,
        cursor: 'pointer',
        lineHeight: '40px',
        color: theme.colors.carbon[8]
      })}
    >
      {isCreating ? (
        <>
          <Loader size="sm" />
          <span style={{ marginLeft: 4 }}>Cluster is creating</span>
        </>
      ) : (
        <>
          <ActionIcon size={20} variant="transparent" c="carbon.8" component="span">
            <IconPlus />
          </ActionIcon>
          <span style={{ marginLeft: 4 }}>Create New Cluster</span>
        </>
      )}
    </Flex>
  )
})

const ClusterCreationItemWrapper = (props: ClusterCreationItemProps) => {
  const {
    store: { activeProjectId }
  } = useStores()
  const visible = useAccessCheck('TidbxCreateInProject', {
    projectId: activeProjectId
  })

  return visible ? <CreateCluster {...props} /> : <>No clusters</>
}

export default ClusterCreationItemWrapper
