import { Alert, Button, Group, List, Loader, Modal, Stack } from '@tidbcloud/uikit'
import { IconAlertCircle, IconCheckCircle } from '@tidbcloud/uikit/icons'
import { useMemo, useState } from 'react'
import { useQuery } from 'react-query'

import { SharedCluster } from 'dbaas/features/ClusterManagement/cluster'
import { CloudProviderConst } from 'dbaas/features/Project'
import { migrationServiceDescribeVpcEndpoint } from 'dbaas/services/api-clients/legacy/serverless'
import { DescribeEndpointRespPhase } from 'dbaas/services/api-clients/legacy/serverless/interface'
import { getErrorMessage } from 'dbaas/services/errorCodes'
import useStores from 'dbaas/stores/useStores'

export const EssentialPrivateLinkCheck = ({
  opened,
  endpointId,
  onClose,
  onAvailable,
  serviceName,
  isAzureMysql,
  onError
}: {
  opened: boolean
  endpointId?: string
  onClose: () => void
  onAvailable: () => void
  serviceName?: string
  isAzureMysql: boolean
  onError?: (msg: string) => void
}) => {
  const {
    store: { tenantData, activeProjectId, currentCluster }
  } = useStores()
  const baseQueryKey = useMemo(
    () => ['essential-private-link', tenantData.id, activeProjectId, currentCluster?.id],
    [activeProjectId, currentCluster?.id, tenantData.id]
  )
  const queryKey = useMemo(() => [...baseQueryKey, endpointId], [baseQueryKey, endpointId])
  const [isAfterPendingAcceptance, setIsAfterPendingAcceptance] = useState(false)
  const {
    data: privateLinkData,
    refetch,
    isFetching
  } = useQuery(
    queryKey,
    () =>
      migrationServiceDescribeVpcEndpoint(tenantData.id, activeProjectId, currentCluster?.id!, {
        endpoint_id: endpointId!
      }),
    {
      enabled: opened && !!endpointId,
      refetchInterval: (data) => {
        if (data?.phase === DescribeEndpointRespPhase.Pending) {
          return 3000
        }
        return false
      },
      retry: false,
      onSuccess(data) {
        if (data.phase === DescribeEndpointRespPhase.PendingAcceptance) {
          setIsAfterPendingAcceptance(true)
        }
      },
      onError: (err) => {
        onError?.(getErrorMessage(err, true) || 'Failed to get private link endpoint status, please try again later.')
      }
    }
  )

  const onContinue = () => {
    onClose()
    onAvailable()
  }

  const modalTitle = useMemo(() => {
    if (privateLinkData?.phase === DescribeEndpointRespPhase.PendingAcceptance) {
      return 'Approve the pending Private Endpoint request'
    }
    if (privateLinkData?.phase === DescribeEndpointRespPhase.Failed) {
      return 'Failed to create Private Endpoint'
    }
    if (privateLinkData?.phase === DescribeEndpointRespPhase.Available) {
      return 'Private Endpoint is available'
    }
    return 'Connect Preparation'
  }, [privateLinkData?.phase])

  const alertMessage = useMemo(() => {
    if (!privateLinkData || privateLinkData.phase === DescribeEndpointRespPhase.Pending) {
      if (privateLinkData && isAfterPendingAcceptance) {
        return (
          <Alert icon={<Loader size="xs" />} title="Just one second">
            Verifying connection...
          </Alert>
        )
      }
      return (
        <Alert icon={<Loader size="xs" />} title="Just one second">
          Creating private link endpoint for you...
        </Alert>
      )
    }
    if (privateLinkData.phase === DescribeEndpointRespPhase.PendingAcceptance) {
      return (
        <Alert icon={<IconCheckCircle />} color="green">
          VPC Endpoint created! Waiting for your approval in the cloud console.
        </Alert>
      )
    }
    if (privateLinkData.phase === DescribeEndpointRespPhase.Failed) {
      return (
        <Alert color="red" icon={<IconAlertCircle />}>
          {privateLinkData.error_message || 'Failed to create Private Endpoint'}
        </Alert>
      )
    }
    if (privateLinkData.phase === DescribeEndpointRespPhase.Available) {
      return (
        <Alert icon={<IconCheckCircle />} color="green">
          VPC Endpoint created and is ready to use!
        </Alert>
      )
    }

    return null
  }, [privateLinkData, isAfterPendingAcceptance])

  return (
    <Modal opened={opened} size="xl" centered withCloseButton={false} onClose={onClose} title={modalTitle}>
      <Stack>
        {alertMessage}

        <Reminder
          serviceName={serviceName}
          isAzureMysql={isAzureMysql}
          cluster={currentCluster!}
          endpoint_id={privateLinkData?.endpoint_id}
        />

        <Group justify="flex-end">
          <Button variant="default" onClick={onClose}>
            Cancel
          </Button>
          {privateLinkData?.phase === DescribeEndpointRespPhase.PendingAcceptance && (
            <Button
              onClick={() => {
                refetch()
              }}
              loading={isFetching}
            >
              Already done, continue
            </Button>
          )}
          {privateLinkData?.phase === DescribeEndpointRespPhase.Available && (
            <Button onClick={onContinue}>Continue</Button>
          )}
        </Group>
      </Stack>
    </Modal>
  )
}

export default EssentialPrivateLinkCheck

function Reminder({
  serviceName,
  endpoint_id,
  cluster,
  isAzureMysql
}: {
  serviceName?: string
  endpoint_id?: string
  cluster?: SharedCluster
  isAzureMysql?: boolean
}) {
  const displayServiceName = serviceName ?? 'N/A'
  const displayEndpointId = endpoint_id ?? 'N/A'
  const consoleName = useMemo(() => {
    if (cluster?.provider === CloudProviderConst.AWS) return 'Amazon VPC Endpoint Service console'
    if (cluster?.provider === CloudProviderConst.ALICLOUD) return 'Alibaba Cloud VPC Endpoint Service console'
    return 'Cloud console'
  }, [cluster?.provider])

  if (isAzureMysql) {
    return (
      <List px={8} py={8}>
        <List.Item>
          Access{' '}
          <a href="https://portal.azure.com/" target="_blank" rel="noreferrer">
            Azure Portal
          </a>{' '}
          and choose one of the two approval paths:
        </List.Item>
        <List.Item>
          Option 1: Azure Database for MySQL Flexible Server → Networking → Private endpoints → select the TiDB Cloud
          connection request → Approve
        </List.Item>
        <List.Item>
          Option 2: Private Link Center → Pending connections → select the TiDB Cloud connection request → Approve.
        </List.Item>
        <List.Item>Return here and continue.</List.Item>
      </List>
    )
  }
  return (
    <p>
      Please go to the {consoleName}, choose the endpoint service named <b>{displayServiceName}</b>, and accept the
      request for VPC endpoint <b>{displayEndpointId}</b>.
    </p>
  )
}
