import {
  ActionIcon,
  Alert,
  Anchor,
  Button,
  CopyButton,
  Group,
  LoadingOverlay,
  notifier,
  Stack,
  Tooltip,
  Box,
  Typography,
  Divider
} from '@tidbcloud/uikit'
import { FormTextInput, CodeBlock } from '@tidbcloud/uikit/biz'
import { IconCheck, IconCopy01, IconInfoCircle } from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'
import { useFormContext } from 'react-hook-form'

import { CloudProviderConst } from 'dbaas/features/Project'
import {
  useCustomerManagedEncryptionKeyServiceCreateCustomerManagedEncryptionKey,
  useCustomerManagedEncryptionKeyServiceShowCmekAccessIamPrincipal
} from 'dbaas/services/api-clients/v2023/dedicated/v1beta1'
import useStores from 'dbaas/stores/useStores'

interface CreateFormProps {
  onClose: () => void
  onSubmit: () => void
}

export const AzureCreateContent = observer(({ onClose, onSubmit }: CreateFormProps) => {
  const {
    store: { tenantData, activeProjectId }
  } = useStores()
  const { watch, handleSubmit } = useFormContext()
  const provider = watch('provider')
  const keyVaultKey = watch('keyVaultKey') as string
  const keyVaultName = watch('keyVaultName') as string
  const region = watch('region')

  const { data: princupalData, isLoading } = useCustomerManagedEncryptionKeyServiceShowCmekAccessIamPrincipal(
    {
      cloudProvider: provider,
      orgId: tenantData.id,
      projectId: activeProjectId,
      regionId: `azure-${region}`
    },
    {
      query: {
        refetchOnMount: false,
        retry: false,
        refetchOnWindowFocus: false,
        enabled: !!(region && tenantData.id && activeProjectId && provider === CloudProviderConst.AZURE)
      }
    }
  )

  const servicePrincipalName = `az ad sp create --id ${princupalData?.azureCmekPrincipal?.appRegistration?.appRegistrationId ?? '{Microsoft_Entra_Application_ID}'}`

  const createAzureCmekMutation = useCustomerManagedEncryptionKeyServiceCreateCustomerManagedEncryptionKey()

  const servicePrincipalJson = (
    <Stack gap="md" px="xl">
      <Box>
        <Typography variant="title-lg">Create Service Principal</Typography>
        <Typography variant="body-lg" mt={4}>
          Please copy and use the provided Microsoft Entra Application Name and Application ID to configure a Service
          Principal for your Azure Key Vault, authorizing TiDB Cloud to use your key for encryption at rest. For more
          details, please refer to
          <a
            href="https://learn.microsoft.com/en-us/entra/identity-platform/app-objects-and-service-principals?tabs=browser"
            target="_blank"
            rel="noreferrer"
          >
            {' '}
            Application and service principal objects in Microsoft Entra ID.
          </a>
        </Typography>
      </Box>

      <Group grow>
        <FormTextInput
          name="applicationName"
          value={princupalData?.azureCmekPrincipal?.appRegistration?.appRegistrationName ?? ''}
          label="Microsoft Entra Application Name"
          rightSection={
            <CopyButton
              value={princupalData?.azureCmekPrincipal?.appRegistration?.appRegistrationName ?? ''}
              timeout={2000}
            >
              {({ copied, copy }) => (
                <Tooltip label={copied ? 'Copied' : 'Copy'} withArrow position="right">
                  <ActionIcon variant="transparent" size={40} c="carbon.8" onClick={copy}>
                    {copied ? <IconCheck size={16} /> : <IconCopy01 size={16} onClick={copy} />}
                  </ActionIcon>
                </Tooltip>
              )}
            </CopyButton>
          }
          disabled
        />
        <FormTextInput
          name="applicationId"
          label="Microsoft Entra Application ID"
          value={princupalData?.azureCmekPrincipal?.appRegistration?.appRegistrationId ?? ''}
          rightSection={
            <CopyButton
              value={princupalData?.azureCmekPrincipal?.appRegistration?.appRegistrationId ?? ''}
              timeout={2000}
            >
              {({ copied, copy }) => (
                <Tooltip label={copied ? 'Copied' : 'Copy'} withArrow position="right">
                  <ActionIcon variant="transparent" size={40} c="carbon.8" onClick={copy}>
                    {copied ? <IconCheck size={16} /> : <IconCopy01 size={16} onClick={copy} />}
                  </ActionIcon>
                </Tooltip>
              )}
            </CopyButton>
          }
          disabled
        />
      </Group>

      <CodeBlock language="bash" foldProps={{ defaultHeight: 300 }} copyContent={servicePrincipalName}>
        {servicePrincipalName}
      </CodeBlock>
    </Stack>
  )

  const keyVaultJson = (
    <Stack gap="md" px="xl">
      <Box>
        <Typography variant="title-lg">Create Your Key Vault</Typography>
        <Typography variant="body-lg" mt={4}>
          Please provide your Key Vault name and Key name prefix, then copy the full key name to create a new encryption
          key in the Key Vault with required identity permission. Learn more about
          <Anchor
            href="https://docs.pingcap.com/tidbcloud/tidb-cloud-encrypt-cmek-azure/"
            target="_blank"
            rel="noreferrer"
            mx={4}
          >
            Create your encryption key.
          </Anchor>
          Instead of manually creating key vault and configuring roles,
          <Anchor
            href="https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Ftcidm.blob.core.windows.net%2Fcmek%2Fazure_cmek_rmt.json%3Fsv%3D2015-04-05%26ss%3Db%26srt%3Dco%26sp%3Drl%26se%3D2029-03-01T00%253A00%253A01.0000000Z%26sig%3DIA02CymcFpYCwoTsqCSJVD%252F8Khh%252F0UAPrkKDeLMIIFc%253D"
            target="_blank"
            rel="noreferrer"
            ml={4}
          >
            click here to create a new key vault with Azure Resource Manager.
          </Anchor>
        </Typography>
      </Box>

      <FormTextInput name="keyVaultName" label="Key Vault Name" />

      <Alert icon={<IconInfoCircle size={16} />}>
        You can either create a new key vault or use an existing one. But for supporting CMEK on Azure, you <b>MUST</b>{' '}
        enable purge protection.
      </Alert>
    </Stack>
  )

  const keyName = (
    <Stack px="xl" gap="md" mb="xl">
      <Group gap="md" align="flex-end">
        <FormTextInput
          size="md"
          name="keyVaultKey"
          sx={{ flex: 1 }}
          label="Key Name"
          rules={{ required: 'Required' }}
          placeholder="Enter your key name prefix"
          styles={(t) => ({
            section: {
              borderLeft: `1px solid ${t.colors.carbon[4]}`,
              paddingLeft: 12,
              backgroundColor: t.colors.carbon[2],
              width: 200,
              justifyContent: 'left'
            }
          })}
          rightSection={
            <Typography variant="body-lg">-{princupalData?.azureCmekPrincipal?.keyVaultKeySuffix}</Typography>
          }
        />

        <CopyButton value={`${keyVaultKey}-${princupalData?.azureCmekPrincipal?.keyVaultKeySuffix}`} timeout={2000}>
          {({ copied, copy }) => (
            <Tooltip label={copied ? 'Copied' : 'Copy'} withArrow position="right">
              <ActionIcon variant="outline" size={40} c="carbon.8" onClick={copy}>
                {copied ? <IconCheck size={16} /> : <IconCopy01 size={16} onClick={copy} />}
              </ActionIcon>
            </Tooltip>
          )}
        </CopyButton>
      </Group>
      <Alert icon={<IconInfoCircle size={16} />} color="yellow">
        For enhanced security, a unique suffix is added to your key name. Please use the full key name provided when
        creating your key in Azure Key Vault. The full key name is sensitive information. Please <b>DON'T</b> share or
        forward it outside your organization.
      </Alert>
    </Stack>
  )

  const createAzureCmek = async () => {
    try {
      await createAzureCmekMutation.mutateAsync({
        data: {
          azureKeyVault: {
            appRegistration: princupalData?.azureCmekPrincipal?.appRegistration,
            keyVaultKey: `${keyVaultKey?.trim()}-${princupalData?.azureCmekPrincipal?.keyVaultKeySuffix}`,
            keyVaultName: keyVaultName?.trim()
          },
          customerManagedEncryptionKeyId: princupalData?.azureCmekPrincipal?.appRegistration?.appRegistrationId,
          projectId: activeProjectId,
          regionId: `azure-${region}`
        },
        params: {
          orgId: tenantData.id,
          projectId: activeProjectId
        }
      })
      onSubmit()
    } catch (e: any) {
      notifier.error(e.originalMessage)
    }
  }

  const buttons = (
    <Group justify="flex-end" px={24} p="md">
      <Button variant="default" onClick={onClose} data-mp-event="mp-cancel-1691461014346">
        Cancel
      </Button>
      <Button
        loading={createAzureCmekMutation.isLoading}
        data-mp-event="Azure cmek create button clicked"
        disabled={!keyVaultKey || !keyVaultName || !princupalData?.azureCmekPrincipal}
        onClick={handleSubmit(createAzureCmek)}
      >
        Test Encryption Key and Create
      </Button>
    </Group>
  )

  return (
    <>
      <LoadingOverlay visible={isLoading} zIndex={1000} overlayProps={{ radius: 'sm', blur: 2 }} />
      <Divider color="carbon.4" />
      {servicePrincipalJson}
      <Divider color="carbon.4" />
      {keyVaultJson}
      {keyName}
      <Divider color="carbon.4" />
      {buttons}
    </>
  )
})

export default AzureCreateContent
