import { notifier } from '@tidbcloud/uikit'
import { Button, Box, Typography, Badge, Flex, ActionIcon, Alert, HoverCard } from '@tidbcloud/uikit'
import { FormSwitch } from '@tidbcloud/uikit/biz'
import { useLocalStorage } from '@tidbcloud/uikit/hooks'
import { IconLinkExternal01, IconCheck, IconInfoCircle } from '@tidbcloud/uikit/icons'
import { useUnmount } from 'ahooks'
import { useEffect, useMemo, useState } from 'react'
import { useFormContext } from 'react-hook-form'
import { useHistory } from 'react-router-dom'

import {
  usePreflightDataApp,
  useGetPreflightRepos,
  useGetDataappAuthorizeUrl,
  useIsGithubLinked
} from 'dbaas/services/dataservice'
import useQuery from 'dbaas/utils/useQuery'

import { useDataApiContext } from '../context'
import Repos from '../CreateApp/Repos'
import { githubInstallUrl, useGithubAuthRequest, showErrorMsg } from '../helpers'

const Index = ({ index }: { index: number | string }) => {
  return (
    <Badge
      styles={(theme) => ({
        root: {
          background: theme.colors.carbon[8],
          color: theme.white,
          borderRadius: '50%',
          padding: 0,
          width: 24,
          height: 24,
          marginRight: 8
        }
      })}
    >
      {index}
    </Badge>
  )
}

const GithubAuth = ({ isCreate = false, children }: { isCreate?: boolean; children?: string | React.ReactNode }) => {
  const { orgId, projectId, editApp, appList } = useDataApiContext()
  const [installed, setInstalled] = useState(false)
  const prelightUrlMutation = usePreflightDataApp()
  const [requestId, setRequestId] = useGithubAuthRequest()
  const [githubConnecting, setGithubConnecting] = useLocalStorage({
    key: 'github_connecting',
    defaultValue: ''
  })
  const [needGetAuthUrl, setNeedGetAuthUrl] = useState(false)
  const [isAuthing, setIsAuthing] = useState(false)
  const [needAuth, setNeedAuth] = useState(true)
  const [defaultRepo, setDefaultRepo] = useState<{
    directory: string
    repository_id: string
    branch: string
  }>()
  const { setValue, watch } = useFormContext()
  const query = useQuery()
  const errMsg = query.get('error')
  const history = useHistory()
  const [reClickCount, setReClickCount] = useState(0)
  const [installReClicked, setInstallReClicked] = useState(false)

  useEffect(() => {
    if (errMsg) {
      notifier.error(errMsg)
    }
  }, [errMsg])

  useUnmount(() => {
    replaceUrlErrMsg()
  })

  const replaceUrlErrMsg = () => {
    history.replace({}, '')
  }

  const isAutoDepChecked = watch('enable_automatic_deployment', true)
  const [isRedirecting, setIsRedirecting] = useState(false)
  const { isSuccess } = useGetPreflightRepos(orgId, projectId, requestId, {
    query: {
      enabled: !!orgId && !!projectId && !!requestId && !!isCreate,
      refetchInterval: false,
      refetchOnWindowFocus: false
    }
  })

  useGetDataappAuthorizeUrl(orgId, projectId, `${editApp?.id}`, {
    query: {
      enabled: !!orgId && !!projectId && !!appList.length && !!editApp?.id && needGetAuthUrl,
      refetchInterval: false,
      refetchOnWindowFocus: false,
      onSuccess: (res) => {
        setGithubConnecting('true')
        res.data?.url && window.open(res.data.url, '_self')
      }
    }
  })

  const { data: authInfo } = useIsGithubLinked(orgId, projectId, `${editApp?.id}`, {
    query: {
      enabled: !!orgId && !!projectId && !!editApp?.id && needAuth && !isCreate,
      refetchInterval: 1000,
      refetchOnWindowFocus: false,
      onSuccess: (res) => {
        if (res.data?.authorized) {
          setNeedAuth(false)
          setIsAuthing(false)
          if (!isCreate) {
            setDefaultRepo({
              directory: res.data?.directory || '',
              repository_id: `${res.data?.repository_id}-${res.data?.installation_id}`,
              branch: res.data?.branch || ''
            })
          }
        }
      }
    }
  })

  useEffect(() => {
    const autoSyncDefaultValue = localStorage.getItem('github_connecting_sync')
    setValue('enable_automatic_deployment', autoSyncDefaultValue !== 'false')
  }, [])

  const authed = useMemo(() => {
    if (!isCreate) {
      return authInfo?.data?.authorized
    }

    return isSuccess && !isRedirecting
  }, [authInfo, isSuccess, githubConnecting])

  const getAuthUrl = async () => {
    try {
      if (!isCreate) {
        setIsAuthing(true)
        setNeedGetAuthUrl(true)
        return
      }

      const res = await prelightUrlMutation.mutateAsync({
        orgId,
        projectId
      })

      if (res.data?.url) {
        setRequestId(`${res.data.preflight_request_id}`)
        setIsRedirecting(true)
        replaceUrlErrMsg()
        window.open(res.data.url, '_self')
      }
    } catch (e) {
      showErrorMsg(e)
    }
  }

  const installSucc = installed || isSuccess || authInfo?.data?.authorized
  const canReAuth = installSucc && installReClicked

  return (
    <>
      <Box
        sx={(theme) => ({
          border: `1px solid ${theme.colors.carbon[5]}`,
          borderRadius: theme.defaultRadius,
          marginTop: 16
        })}
      >
        <Flex justify="space-between" p="16px 24px">
          <Flex align="center">
            <Index index={1} />
            <Typography variant="title-md">Install the TiDB Cloud Data Service GitHub Plugin</Typography>
          </Flex>
          <Button
            variant={installSucc ? 'default' : 'light'}
            size="sm"
            c={installSucc ? 'carbon.8' : 'peacock.7'}
            data-mp-event="Dataservice install on github button clicked"
            onClick={() => {
              setInstalled(true)
              window.open(githubInstallUrl())
              setInstallReClicked(true)
              setReClickCount(reClickCount + 1)
            }}
          >
            Install on GitHub
            <ActionIcon aria-hidden c={installSucc ? 'carbon.8' : 'peacock.7'} size={16} ml={6}>
              <IconLinkExternal01 size={16} />
            </ActionIcon>
          </Button>
        </Flex>

        <Flex
          justify="space-between"
          p="16px 24px"
          sx={(theme) => ({
            borderTop: `1px solid ${theme.colors.carbon[5]}`,
            borderBottom: `1px solid ${theme.colors.carbon[5]}`
          })}
        >
          <Flex align="center">
            <Index index={2} />
            <Typography variant="title-md">GitHub Authorization</Typography>
          </Flex>
          <Button
            variant={!!errMsg || canReAuth || (installed && !authed) ? 'light' : 'default'}
            disabled={errMsg || canReAuth ? false : !installed || authed}
            size="sm"
            loading={prelightUrlMutation.isLoading || isAuthing || isRedirecting}
            data-mp-event="Dataservice authorize button clicked"
            onClick={getAuthUrl}
          >
            {!errMsg && authed && !canReAuth ? (
              <>
                <ActionIcon aria-hidden c="carbon.6">
                  <IconCheck size={16} />
                </ActionIcon>
                Authorized
              </>
            ) : (
              'Authorize'
            )}
          </Button>
        </Flex>
        <Flex justify="space-between" p="16px 24px" direction="column">
          <Flex align="center">
            <Index index={3} />
            <Typography variant="title-md">Select Repository, Branch and Directory</Typography>
            <HoverCard width={420} position="top" withArrow shadow="md" zIndex={9999}>
              <HoverCard.Target>
                <ActionIcon aria-label="More info" size={20} ml={4}>
                  <IconInfoCircle size={16} />
                </ActionIcon>
              </HoverCard.Target>
              <HoverCard.Dropdown>
                In the chosen directory, we'll create a configuration for this Data App, which includes specific folders
                ('data_sources' and 'http_endpoints') and a file named 'dataapp_config.json'. Any existing directories
                and files with different names will remain unaffected.
              </HoverCard.Dropdown>
            </HoverCard>
          </Flex>
          <Repos authed={!!authed && !errMsg} isCreate={isCreate} defaultValue={defaultRepo} />
        </Flex>

        {!isCreate && (
          <Flex
            justify="space-between"
            p="16px 24px"
            sx={(theme) => ({
              borderTop: `1px solid ${theme.colors.carbon[5]}`
            })}
          >
            <Flex align="center">
              <Index index={4} />
              <Typography variant="title-md">Configure Auto Sync & Deployment </Typography>
            </Flex>
            <FormSwitch
              name="enable_automatic_deployment"
              size="md"
              onChange={(checked) => localStorage.setItem('github_connecting_sync', `${!checked}`)}
            />
          </Flex>
        )}
      </Box>
      {!isAutoDepChecked && !isCreate && (
        <Alert color="yellow" mt={16}>
          Notice: Please enable this setting to ensure the DataApp configuration remains synchronized between the TiDB
          Cloud console and GitHub. In case of testing purposes, please keep it turned off.
        </Alert>
      )}
      {children}
    </>
  )
}

export default GithubAuth
