import {
  Stack,
  SimpleGrid,
  Group,
  TextInput,
  Select,
  Box,
  Button,
  Typography,
  Alert,
  Tabs,
  PrismProps
} from '@tidbcloud/uikit'
import { CodeBlock } from '@tidbcloud/uikit/biz'
import { IconFileMinus03, IconTerminalSquare } from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'

import { AccessDeniedHoverHint, AccessGuard } from 'dbaas/contexts/access-control'

import { NetworkType } from '../types'

import { ConnectionClientFooter } from './Footer'
import {
  isParamsBlock,
  getConnCode,
  rootClientOptions,
  useCodeCopy,
  getCodeVarData,
  useConnections,
  useDownloadCA
} from './helpers'
import { ParamsBlock } from './ParamsBlock'

const icons = {
  terminal: <IconTerminalSquare size={16} />,
  file: <IconFileMinus03 size={16} />
}

interface ConnectionClientBlockProps {
  clusterId: string | undefined
  pwdInited?: boolean
  networkType: NetworkType
  client: string
  onClientChange: (client: string) => void
  /**
   * @deprecated It's unnecessary now.
   */
  currentPwd?: string
  onPwdSet: () => void
  caRequired?: boolean
  host: string | undefined
  port: number | undefined
  userToken: string | undefined
}

export const ConnectionClientBlock = observer(
  ({
    clusterId,
    pwdInited,
    networkType,
    client: rootClient,
    onClientChange: onRootClientChange,
    onPwdSet,
    caRequired,
    host,
    port,
    userToken
  }: ConnectionClientBlockProps) => {
    const codeVars = getCodeVarData({
      endpoint: {
        host,
        port
      },
      db: 'test',
      userToken
    })
    const { download } = useDownloadCA(clusterId || '')

    /**
     * connection client and codes
     */
    const { withSubClient, rootConn, subConns, currentConn, activeSubConnId, onSubConnIdChange } = useConnections({
      networkType,
      rootClient
    })

    const codeHandlers = useCodeCopy({
      networkType,
      rootClient,
      mpEvents: {
        freeCopy: 'Connection string copied',
        btnCopy: 'Connection copy button clicked'
      }
    })

    if (!clusterId) {
      return null
    }

    return (
      <Stack
        p="xl"
        bg="carbon.3"
        sx={(theme) => ({
          borderBottomLeftRadius: theme.defaultRadius,
          borderBottomRightRadius: theme.defaultRadius
        })}
      >
        <SimpleGrid cols={2} verticalSpacing="xl">
          <Group gap={0} wrap="nowrap">
            <TextInput
              placeholder="Connect With"
              readOnly
              styles={(theme) => ({
                wrapper: {
                  width: 'min-content',
                  minWidth: 128,
                  maxWidth: 'min-content'
                },
                input: {
                  borderTopRightRadius: 0,
                  borderBottomRightRadius: 0,
                  borderRight: 'none',
                  '&:focus, &:focus-within': {
                    borderColor: theme.colors.carbon[5]
                  },
                  '&::placeholder': {
                    color: theme.colors.carbon[7]
                  }
                }
              })}
            />
            <Select
              value={rootClient}
              data={rootClientOptions}
              onChange={(val) => onRootClientChange(val || '')}
              styles={{
                root: {
                  flexGrow: 1
                },
                input: {
                  borderTopLeftRadius: 0,
                  borderBottomLeftRadius: 0
                }
              }}
              data-testid="dedicated-connection-client-selector"
            />
          </Group>
          <Box ta="right">
            {!pwdInited && (
              <AccessDeniedHoverHint id="ClusterSecurityAction">
                {({ accessible }) => (
                  <Button
                    variant="default"
                    disabled={!accessible}
                    onClick={onPwdSet}
                    data-mp-event="Set Root Password Button Clicked"
                    data-mp-source="connection-modal"
                    data-testid="dedicated-connection-set-root-password-btn"
                  >
                    Set Root Password
                  </Button>
                )}
              </AccessDeniedHoverHint>
            )}
          </Box>
        </SimpleGrid>
        {!pwdInited && (
          <Typography variant="body-lg">
            Your cluster doesn't have a root password yet.{' '}
            <AccessGuard id="ClusterSecurityAction" fallback="Please ask your admin to set a root password.">
              Please set a root password at first and keep it in a safe place.
            </AccessGuard>
          </Typography>
        )}
        {/* FIXME: It's still up for discussion whether the
                   reset password entry is available here.
        */}
        {/* {pwdInited && (
          <Typography variant="body-lg">
            Replace {'<'}PASSWORD{'>'} with your password in the connection string.{' '}
            <AccessGuard id="ClusterSecurityAction">
              Forget the root password?{' '}
              <Button
                variant="white"
                onClick={onPwdSet}
                bg="transparent"
                fw={600}
                h={20}
                px={4}
                data-mp-event="Reset password Button Clicked"
                data-testid="dedicated-connection-reset-password-btn"
              >
                Reset it
              </Button>
            </AccessGuard>
          </Typography>
        )} */}

        {caRequired && (
          <Alert>
            Download{' '}
            <a onClick={download} data-mp-event="Download TiDB Cloud Root CA Link Clicked">
              CA cert
            </a>{' '}
            for client TLS configuration at first time and replace {'<'}CA_PATH{'>'} with your local path.
          </Alert>
        )}

        {!withSubClient &&
          rootConn &&
          (isParamsBlock(rootConn.type) ? (
            <Box
              sx={(theme) => ({
                backgroundColor: theme.colors.carbon[1],
                border: `1px solid ${theme.colors.carbon[5]}`,
                borderRadius: theme.defaultRadius
              })}
            >
              <ParamsBlock networkType={networkType} vars={codeVars} />
            </Box>
          ) : (
            <CodeBlock
              language={rootConn.lang as PrismProps['language']}
              codeHighlightProps={{
                onCopy: () => codeHandlers.onSelectionCopy()
              }}
              onCopyClick={codeHandlers.onCopyBtnClick}
              sx={(theme) => ({
                '&>div:first-of-type': {
                  backgroundColor: theme.colors.carbon[1]
                }
              })}
              data-testid="dedicated-connection-codeblock"
            >
              {getConnCode(rootConn?.code, codeVars)}
            </CodeBlock>
          ))}
        {withSubClient && (
          <Tabs
            value={activeSubConnId}
            onChange={onSubConnIdChange}
            styles={(theme) => ({
              root: {
                backgroundColor: theme.colors.carbon[1],
                border: `1px solid ${theme.colors.carbon[5]}`,
                borderRadius: theme.defaultRadius
              },
              tabsList: {
                gap: 24,
                borderBottom: `1px solid ${theme.colors.carbon[4]}`
              },
              tabIcon: {
                '&:not(:only-child)': {
                  marginRight: 4
                }
              }
            })}
            data-testid="dedicated-connection-codeblock"
          >
            <Tabs.List mx="md">
              {subConns?.map((item) => (
                <Tabs.Tab key={item.id} value={item.id} leftSection={icons[item.iconType]} pt="md" mb={-1}>
                  {item.label}
                </Tabs.Tab>
              ))}
            </Tabs.List>
            {subConns?.map((item) => (
              <Tabs.Panel key={item.id} value={item.id}>
                {isParamsBlock(item.type) ? (
                  <ParamsBlock networkType={networkType} vars={codeVars} />
                ) : (
                  <CodeBlock
                    language={item.lang as PrismProps['language']}
                    codeHighlightProps={{
                      onCopy: () => codeHandlers.onSelectionCopy(item.label)
                    }}
                    onCopyClick={() => codeHandlers.onCopyBtnClick(item.label)}
                    sx={{
                      '&>div:first-of-type': {
                        backgroundColor: 'transparent',
                        borderWidth: 0
                      }
                    }}
                  >
                    {getConnCode(item.code, codeVars)}
                  </CodeBlock>
                )}
              </Tabs.Panel>
            ))}
          </Tabs>
        )}
        <ConnectionClientFooter docLink={currentConn?.doc} client={rootClient} />
      </Stack>
    )
  }
)
