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

import { useCreatePrivateLinkEndpoint, useGetPrivateLinkEndpoint } from 'dbaas/services/dataflow'
import { GetPrivateLinkEndpointRespPhase } from 'dbaas/services/dataflow/interface'
import { getErrorMessage } from 'dbaas/services/errorCodes'
import useStores from 'dbaas/stores/useStores'

export const PrivateLinkCheck = ({
  opened,
  onClose,
  onAvailable,
  resourceId,
  onError
}: {
  opened: boolean
  onClose: () => void
  onAvailable: () => void
  resourceId: string
  onError?: (msg: string) => void
}) => {
  const {
    store: { tenantData, activeProjectId, currentCluster }
  } = useStores()

  const [privateLinkId, setPrivateLinkId] = useState<string>()
  const [loading, setLoading] = useState(false)
  const [isAfterPendingAcceptance, setIsAfterPendingAcceptance] = useState(false)
  const [showPendingHint, setShowPendingHint] = useState(false)
  const createPlMutation = useCreatePrivateLinkEndpoint()

  const { data: privateLinkData, refetch } = useGetPrivateLinkEndpoint(
    tenantData.id,
    activeProjectId,
    currentCluster?.id!,
    privateLinkId!,
    {
      query: {
        enabled: Boolean(privateLinkId) && opened,
        refetchInterval: 3000,
        onSuccess(data) {
          if (data.phase === GetPrivateLinkEndpointRespPhase.Available && opened) {
            onClose()
            onAvailable()
          }
          if (data.phase === GetPrivateLinkEndpointRespPhase.PendingAcceptance) {
            setIsAfterPendingAcceptance(true)
          }
        }
      }
    }
  )

  useEffect(() => {
    if (!opened) return
    if (privateLinkId) return
    ;(async () => {
      try {
        const { id } = await createPlMutation.mutateAsync({
          orgId: tenantData.id,
          projectId: activeProjectId,
          clusterId: currentCluster?.id!,
          data: {
            endpoint_service_name: resourceId
          }
        })
        setPrivateLinkId(id)
        await refetch()
      } catch (e) {
        const msg = getErrorMessage(e)
        onError?.(msg)
        onClose()
      }
    })()
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [opened, resourceId])

  const onConfirmContinue = async () => {
    setLoading(true)
    const res = await refetch()
    setLoading(false)
    const phase = res.data?.phase
    if (phase === GetPrivateLinkEndpointRespPhase.Available) {
      onClose()
      onAvailable()
      return
    }
    if (phase === GetPrivateLinkEndpointRespPhase.PendingAcceptance) {
      setShowPendingHint(true)
    }
  }

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

  const alertMessage = useMemo(() => {
    if (createPlMutation.isLoading || !privateLinkData) {
      return (
        <Alert icon={<Loader size="xs" />} title="Just one second">
          Creating private link endpoint for you...
        </Alert>
      )
    }
    if (privateLinkData?.phase === GetPrivateLinkEndpointRespPhase.Pending) {
      if (isAfterPendingAcceptance) {
        return (
          <Alert icon={<Loader size="xs" />} title="Just one second">
            Verifying connection...
          </Alert>
        )
      }
      return (
        <Alert icon={<Loader size="xs" />} title="Just one second">
          Still creating private link endpoint for you.
        </Alert>
      )
    }
    if (privateLinkData?.phase === GetPrivateLinkEndpointRespPhase.Failed) {
      return (
        <Alert color="red" icon={<IconAlertCircle />}>
          {privateLinkData?.message}
        </Alert>
      )
    }
    if (privateLinkData?.phase === GetPrivateLinkEndpointRespPhase.Available) {
      return (
        <Alert icon={<IconCheckCircle />} color="green">
          VPC Endpoint created and is ready to use!
        </Alert>
      )
    }
    if (privateLinkData?.phase === GetPrivateLinkEndpointRespPhase.PendingAcceptance) {
      return (
        <Alert icon={<IconCheckCircle />} color="green">
          <Stack gap={4}>
            <div>VPC Endpoint created! Waiting for your approval in the cloud console.</div>
            {showPendingHint && (
              <div>The approval is still being processed. Please wait about one minute and try again.</div>
            )}
          </Stack>
        </Alert>
      )
    }
    return (
      <Alert icon={<IconCheckCircle />} color="green">
        VPC Endpoint created!
      </Alert>
    )
  }, [privateLinkData, isAfterPendingAcceptance, showPendingHint, createPlMutation.isLoading])

  return (
    <Modal
      opened={opened}
      size="xl"
      centered
      withCloseButton={false}
      onClose={onClose}
      title={
        <Text fw={700} fz={20}>
          {modalTitle}
        </Text>
      }
    >
      <Stack>
        {alertMessage}

        {privateLinkData?.phase === GetPrivateLinkEndpointRespPhase.PendingAcceptance && (
          <List px={8} py={8}>
            <List.Item>
              Access{' '}
              <a href="https://portal.azure.com/" target="_blank" rel="noreferrer">
                Azure Portal
              </a>{' '}
              and approve the pending connection request:
            </List.Item>
            <List.Item>
              Storage Account → Networking → Private endpoints → select the TiDB Cloud connection request → Approve
            </List.Item>
            <List.Item>Return here and continue.</List.Item>
          </List>
        )}

        <Group justify="flex-end">
          <Button variant="default" onClick={onClose}>
            Cancel
          </Button>
          {privateLinkData?.phase === GetPrivateLinkEndpointRespPhase.PendingAcceptance ? (
            <Button onClick={onConfirmContinue} loading={loading}>
              Already done, continue
            </Button>
          ) : null}
        </Group>
      </Stack>
    </Modal>
  )
}

export default PrivateLinkCheck
