import { Box, Button, Group, Modal, notifier, Typography } from '@tidbcloud/uikit'
import { DotBadge } from '@tidbcloud/uikit/biz'
import { useDisclosure } from '@tidbcloud/uikit/hooks'
import { useState } from 'react'

import { HeroComponent, isHeroQueryReady } from 'dbaas/components/Measurement'
import { AccessDeniedHoverHint } from 'dbaas/contexts/access-control/ui/AccessDeniedHoverHint'
import {
  useTidbNodeGroupServiceGetPublicEndpointSetting,
  useTidbNodeGroupServiceUpdatePublicEndpointSetting
} from 'dbaas/services/api-clients/v2023/dedicated/v1beta1'
import { getErrorMessage } from 'dbaas/services/errorCodes'
import useStores from 'dbaas/stores/useStores'

import { IP_CLUSTER_UNREADY_CODE, IP_TOO_QUICK } from './consts'
import IPErrorModal from './IpAccess/IPErrorModal'

export const PublicEndpoint = ({ nodeGroupId, clusterId }: { nodeGroupId?: string; clusterId: string }) => {
  const [modalOpened, modalHandlers] = useDisclosure()
  const [modalMsg, setModalMsg] = useState('')

  const {
    store: {
      lastVisitLocation: { orgId, projectId }
    }
  } = useStores()

  const { data, isFetched, isError, refetch } = useTidbNodeGroupServiceGetPublicEndpointSetting(
    clusterId,
    nodeGroupId || '',
    {
      orgId,
      projectId
    },
    {
      query: {
        enabled: !!clusterId && !!nodeGroupId,
        refetchOnMount: false,
        refetchOnWindowFocus: false
      }
    }
  )

  const enabled = data?.enabled ?? false

  const { mutateAsync, isLoading: switchIsLoading } = useTidbNodeGroupServiceUpdatePublicEndpointSetting()

  const handleSwitchSetting = async () => {
    try {
      await mutateAsync({
        clusterId,
        tidbNodeGroupId: nodeGroupId ?? '',
        data: {
          enabled: !enabled,
          ipAccessList: data?.ipAccessList
        },
        params: {
          orgId,
          projectId
        }
      })
      refetch()
      modalHandlers.close()
    } catch (e: any) {
      const errorCode = e?.originalError?.details?.[0]?.servingData
      if (errorCode === IP_TOO_QUICK || errorCode === IP_CLUSTER_UNREADY_CODE) {
        setModalMsg(getErrorMessage(e, true))
      } else {
        notifier.error(getErrorMessage(e, true))
      }
    }
  }

  const status = (
    <DotBadge color={enabled ? 'green' : 'carbon'} bg={enabled ? 'green.1' : 'carbon.2'}>
      {enabled ? 'Enabled' : 'Disabled'}
    </DotBadge>
  )

  const switchButton = (
    <AccessDeniedHoverHint id="ProjectNetworkAction">
      {({ accessible }) =>
        enabled ? (
          <Button
            disabled={!accessible}
            variant="default"
            onClick={modalHandlers.open}
            size="sm"
            data-mp-event="Disable dedicated public endpoint button clicked"
          >
            Disable
          </Button>
        ) : (
          <Button
            disabled={!accessible}
            variant="default"
            size="sm"
            loading={switchIsLoading}
            onClick={handleSwitchSetting}
            data-mp-event="Enable dedicated public endpoint button clicked"
          >
            Enable
          </Button>
        )
      }
    </AccessDeniedHoverHint>
  )

  return (
    <>
      <HeroComponent ready={isHeroQueryReady({ isFetched, isError })} />
      <Group justify="space-between" align="flex-start" wrap="nowrap" gap="xl">
        <Box sx={{ flexShrink: 1 }}>
          <Group gap="md" mb={8}>
            <Typography variant="title-lg">Public Endpoint</Typography>
            {data && status}
          </Group>
          <Typography variant="body-lg">
            The public endpoint is a publicly resolvable DNS address. Enabling this allows the cluster accessible
            through the internet.
          </Typography>
        </Box>
        {data && switchButton}
      </Group>
      <Modal title="Disable Public Endpoint" centered size="md" opened={modalOpened} onClose={modalHandlers.close}>
        <Typography variant="body-lg" mb="xl">
          You are about to disable the public endpoint for your TiDB Dedicated cluster. Please note that while this
          action will not impact any existing connections to the public endpoint, it will prevent new connections from
          being established through it.
        </Typography>
        <Group justify="flex-end">
          <Button
            variant="default"
            onClick={modalHandlers.close}
            data-mp-event="Cancel disabling dedicated public endpoint button clicked"
          >
            Cancel
          </Button>
          <Button
            color="red"
            variant="light"
            loading={switchIsLoading}
            onClick={handleSwitchSetting}
            data-mp-event="Disabled public endpoint"
          >
            Disable
          </Button>
        </Group>
      </Modal>

      <IPErrorModal
        opened={!!modalMsg.length}
        onClose={() => setModalMsg('')}
        message={modalMsg}
        eventName="Public endpoint disable/endable IP too quickly error modal OK button clicked"
      />
    </>
  )
}
