import { Box, Button, Flex, HoverCard, Modal, Typography } from '@tidbcloud/uikit'
import { Form, FormSelect } from '@tidbcloud/uikit/biz'
import { useDisclosure } from '@tidbcloud/uikit/hooks'
import { IconPlus, IconInfoCircle, IconGithub } from '@tidbcloud/uikit/icons'
import { debounce } from 'lodash-es'
import { observer } from 'mobx-react'
import { forwardRef, useCallback, useContext, useState } from 'react'
import { useFormContext } from 'react-hook-form'

import config from 'config'
import { AccessDeniedHoverHint } from 'dbaas/contexts/access-control/ui/AccessDeniedHoverHint'
import { SharedCluster } from 'dbaas/features/ClusterManagement/cluster'
import { createConnectionService, deleteConnectionService } from 'dbaas/services/integration'
import useStores from 'dbaas/stores/useStores'
import { eventTracking } from 'dbaas/utils/tracking'

import { ServerlessBranchContext, openWindow } from './context'
import { CreateBranchModal } from './CreateBranchModal'

type ConnectFormValues = {
  account: ''
  repo: ''
}

interface ItemProps {
  label: string
  value: string
}

const ConnectForm = observer(() => {
  const { accountList, repoList, getGithubAccounts, getRepoList } = useContext(
    ServerlessBranchContext
  ) as ServerlessBranchContext

  const { watch } = useFormContext<ConnectFormValues>()

  const account = watch('account')

  const handleAccountChange = useCallback(
    (v: any) => {
      if (v === 'other') {
        openWindow(config.GITHUB_INSTALL_URL, 'gitHubInstall', 800, 600)
      } else {
        v && getRepoList(v)
      }
    },
    [getRepoList]
  )

  const handleRepoChange = useCallback(
    (query: string) => {
      account && getRepoList(account, query)
    },
    [account]
  )

  const debounceFunc = debounce(handleRepoChange, 300)

  const SelectItem = forwardRef<HTMLDivElement, ItemProps>(({ label, value, ...others }: ItemProps, ref) => (
    <div ref={ref} {...others}>
      {value === 'other' ? (
        <Flex align="center">
          <Box
            component={IconPlus}
            size={10}
            mr={10}
            sx={(theme) => ({ path: { stroke: theme.colors.blue[7] } })}
          ></Box>
          <Typography color="peacock.7" fw={600} fz={14}>
            Install Other Account
          </Typography>
        </Flex>
      ) : (
        label
      )}
    </div>
  ))

  return (
    <>
      {accountList && (
        <FormSelect
          label="GitHub Account"
          name="account"
          mt={8}
          mb={24}
          renderOption={(item) => <SelectItem {...item.option} />}
          rules={{ required: 'Required' }}
          onChange={(v) => handleAccountChange(v)}
          onDropdownOpen={() => getGithubAccounts()}
          placeholder="Select Git Account"
          data={accountList
            .map((v) => ({ label: v.name || '', value: v.installation_id?.toString() || '' }))
            .concat({ label: '', value: 'other' })}
        />
      )}
      <FormSelect
        label="GitHub Repository"
        name="repo"
        mt={8}
        mb={24}
        searchable
        onSearchChange={(v) => debounceFunc(v)}
        rules={{ required: 'Required' }}
        placeholder="Select Git Repository"
        data={repoList.map((v) => ({ label: v.full_name || '', value: v.full_name?.toString() || '' }))}
      />
    </>
  )
})

export const BranchTopButton: React.FC<React.PropsWithChildren<{ cluster: SharedCluster }>> = observer((props) => {
  const {
    store: { tenantData, activeProject }
  } = useStores()
  const branchActionAccessCheckProps = {
    id: 'TidbxBranchAction' as const,
    scopeProps: { tidbId: props.cluster.id }
  }

  const {
    isConnect,
    githubConnect,
    connectModalShow,
    setConnectModalShow,
    connectionLoading,
    getGithubConnect,
    connectInfo,
    branchList,
    getBranchList
  } = useContext(ServerlessBranchContext) as ServerlessBranchContext

  const [createModalOpened, createModalHandlers] = useDisclosure()

  // only starter cluster can use connect to github
  const showConnectButton = props.cluster?.computed?.isStarter

  const [disconnectModalShow, setDisconnectModalShow] = useState<boolean>(false)

  const githubDisconnect = useCallback(async () => {
    eventTracking('Serverless branch github disconnect submit')
    await deleteConnectionService(tenantData.id, activeProject.id, props.cluster.id)
    getGithubConnect()
    setDisconnectModalShow(false)
  }, [props.cluster.id])

  const handleConnectConfirm = useCallback(
    async (value: ConnectFormValues) => {
      eventTracking('Serverless branch github connect submit')
      if (props.cluster.id) {
        await createConnectionService(tenantData.id, activeProject.id, props.cluster.id, {
          repo_name: value.repo,
          git_provider: 'github'
        })
        getGithubConnect()
        setConnectModalShow(false)
      }
    },
    [props.cluster.id]
  )

  const connectButton = isConnect ? (
    <AccessDeniedHoverHint {...branchActionAccessCheckProps}>
      {({ accessible }) => (
        <Button
          disabled={!accessible}
          leftSection={<IconGithub width={14} height={14} />}
          size="sm"
          px={12}
          variant="default"
          data-mp-event="Serverless branch github disconnect button clicked"
          onClick={() => setDisconnectModalShow(true)}
        >
          Disconnect
        </Button>
      )}
    </AccessDeniedHoverHint>
  ) : (
    <AccessDeniedHoverHint {...branchActionAccessCheckProps}>
      {({ accessible }) => (
        <HoverCard shadow="md" closeDelay={100} position="top" withArrow disabled={!accessible}>
          <HoverCard.Target>
            <div>
              <Button
                disabled={!accessible}
                size="sm"
                px={12}
                loading={connectionLoading}
                leftSection={<IconGithub width={14} height={14} />}
                rightSection={<IconInfoCircle size={14} />}
                variant="default"
                onClick={githubConnect}
                data-mp-event="Serverless branch github connect button clicked"
              >
                Connect to GitHub
              </Button>
            </div>
          </HoverCard.Target>
          <HoverCard.Dropdown>
            <Typography variant="body-lg" maw={450}>
              Connect to GitHub brings database branching to your GitHub workflows. See{' '}
              <a href="https://docs.pingcap.com/tidbcloud/branch-github-integration" target="_blank" rel="noreferrer">
                branching GitHub integration
              </a>{' '}
              for more details.
            </Typography>
          </HoverCard.Dropdown>
        </HoverCard>
      )}
    </AccessDeniedHoverHint>
  )

  const connectModal = (
    <Modal
      title="Connect to GitHub"
      centered
      trapFocus={false}
      opened={connectModalShow}
      onClose={() => setConnectModalShow(false)}
    >
      <Form<ConnectFormValues>
        actionsProps={{
          confirmText: 'Connect'
        }}
        onCancel={() => setConnectModalShow(false)}
        onSubmit={handleConnectConfirm}
      >
        <ConnectForm />
      </Form>
    </Modal>
  )

  const disconnectModal = (
    <Modal
      title="Disconnect to GitHub"
      centered
      trapFocus={false}
      opened={disconnectModalShow}
      onClose={() => setDisconnectModalShow(false)}
    >
      <Form
        actionsProps={{
          confirmText: 'Disconnect',
          confirmProps: {
            color: 'red'
          }
        }}
        onSubmit={githubDisconnect}
        onCancel={() => setDisconnectModalShow(false)}
      >
        <Flex mb={16}>
          <IconGithub width={20} height={20} />
          <a href={`https://github.com/${connectInfo?.repo_name}`} target="_blank" rel="noreferrer">
            <Typography variant="action-md" c="carbon.9" ml={8}>
              {connectInfo?.repo_name}
            </Typography>
          </a>
        </Flex>
        <Typography variant="body-lg">
          tidb-cloud-branching app will no longer work in your GitHub repository. Do you want to proceed?
        </Typography>
      </Form>
    </Modal>
  )

  return (
    <>
      <Flex justify="space-between" align="center" ml="md">
        <Flex gap={8}>
          <AccessDeniedHoverHint {...branchActionAccessCheckProps}>
            {({ accessible }) => (
              <Button
                disabled={!accessible}
                data-testid="create-branch"
                size="sm"
                px={12}
                onClick={createModalHandlers.open}
                data-mp-event="mp-createbranch-1691461012595"
              >
                Create Branch
              </Button>
            )}
          </AccessDeniedHoverHint>
          {showConnectButton && connectButton}
        </Flex>
      </Flex>
      <CreateBranchModal
        opened={createModalOpened}
        clusterId={props.cluster.id}
        branchList={branchList?.branches ?? []}
        createTime={props.cluster.createTime}
        onClose={createModalHandlers.close}
        onConfirm={getBranchList}
      />
      {connectModal}
      {disconnectModal}
    </>
  )
})
