import { Anchor, Button, Card, Stack, useMantineTheme } from '@tidbcloud/uikit'
import { Alert, Box, Typography } from '@tidbcloud/uikit'
import { IconAnnotationAlert, IconInfoCircle } from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'
import { useMemo, useState } from 'react'

import { HoverHintReason, ReasonHoverHint } from 'dbaas/components/HoverHint/ReasonHoverHint'
import { HeroComponent } from 'dbaas/components/Measurement'
import { useAccessDeniedHintReason, useAccessCheck } from 'dbaas/contexts/access-control'
import { ALERT_SUBSCRIBER_TYPE_LABELS } from 'dbaas/features/AlertSubscription'
import { getTidbStateToPassivePhrase } from 'dbaas/screens/NextGen/shared/model/tidb-state'
import { useSharedTiDBContext } from 'dbaas/screens/NextGen/tidb-mgmt-container/shared/tidb-context'
import { TiDBPageShell } from 'dbaas/screens/NextGen/tidb-mgmt-container/shared/TiDBPageShell'
import { useListNextGenAlertSubscribers, useGetNextGenAlertSubscriberQuota } from 'dbaas/services/clinicService'
import { EntityAlertSubscribersItem, EntityAlertSubscriberType } from 'dbaas/services/clinicService/interface'
import useStores from 'dbaas/stores/useStores'

import { CreateModal, useCanUseExternalSubscription } from './CreateModal'
import { DeleteModal } from './DeleteModal'
import SubscribersTable from './shared/SubscriberTable'

const SUBSCRIBE_TIPS: { [k: string]: JSX.Element } = {
  [EntityAlertSubscriberType.SLACK]: <>Please refer to documentation to learn how to set up.</>,
  [EntityAlertSubscriberType.ZOOM]: <>Please refer to documentation to learn how to set up.</>
}

const SUBSCRIBER_TYPES: { label: string; value: EntityAlertSubscriberType; tip?: JSX.Element }[] = Object.values(
  EntityAlertSubscriberType
).map((t) => ({
  label: ALERT_SUBSCRIBER_TYPE_LABELS[t],
  value: t,
  tip: SUBSCRIBE_TIPS[t]
}))

const AlertsSubscription = observer(
  ({ showAddSubscriber, closeAddSubscriber }: { showAddSubscriber: boolean; closeAddSubscriber: () => void }) => {
    const { colors } = useMantineTheme()
    const {
      store: { tenantData }
    } = useStores()
    const tidb = useSharedTiDBContext()
    const { isFetched, isLoading, refetch, data } = useListNextGenAlertSubscribers(tenantData.id, tidb.tidbId!)
    const [selectedSubscriber, setSelectedSubscriber] = useState<EntityAlertSubscribersItem | null>(null)
    const accessible = useAccessCheck('TidbxAlertSubscriptionAction')

    const dataByType = useMemo(() => {
      if (!data) {
        return undefined
      }
      return SUBSCRIBER_TYPES.map((t) => ({
        ...t,
        data: data.alertSubscribers?.filter((d) => d.subscriberType === t.value)
      }))
    }, [data])

    const noData = dataByType?.every((group) => !group.data?.length)

    return (
      <Stack gap="xl">
        {isFetched && <HeroComponent />}

        <Alert icon={<IconInfoCircle size={12} />} color="peacock">
          By subscribing to email alerts, you can receive notifications for alerts from TiDB Cloud. Refer to{' '}
          <Anchor
            href="https://docs.pingcap.com/tidbcloud/monitor-built-in-alerting"
            target="_blank"
            rel="noreferrer"
            data-mp-event="Alert Subscription Documentation Link Clicked"
            data-mp-source="Alerts"
          >
            TiDB Cloud Built-in Alerting
          </Anchor>{' '}
          to learn what alerts come with TiDB Cloud and what actions you may want to take when you receive an alert.
        </Alert>

        <Box>
          {noData && (
            <Stack justify="center" align="center" mih={512}>
              <IconAnnotationAlert size={48} color={colors.carbon[7]} />
              <Typography variant="title-lg" fz={18} c="carbon.7">
                Get started by adding subscriber
              </Typography>
              <Typography variant="body-lg" c="carbon.7" w={300} sx={{ textAlign: 'center' }}>
                Alert subscription is used to send system notifications to subscribers.
              </Typography>
            </Stack>
          )}
          <Stack gap="xl">
            {dataByType?.map((group) =>
              !!group.data?.length ? (
                <Card p="xl">
                  <Stack>
                    <Stack gap={4}>
                      <Typography variant="title-lg">{group.label}</Typography>
                      {!!group.tip && (
                        <Typography variant="body-lg" c="carbon.7">
                          {group.tip}
                        </Typography>
                      )}
                    </Stack>
                    <SubscribersTable
                      accessible={accessible}
                      showActions={accessible}
                      type={group.value}
                      subscribers={group.data || []}
                      unsubscribe={setSelectedSubscriber}
                      loading={isLoading}
                    />
                  </Stack>
                </Card>
              ) : (
                <></>
              )
            )}
          </Stack>
        </Box>

        <CreateModal
          opened={showAddSubscriber}
          orgId={tenantData.id}
          clusterId={tidb.tidbId!}
          isEssentialV2={tidb.computed.isEssentialV2}
          onCancel={closeAddSubscriber}
          onSuccess={() => {
            closeAddSubscriber()
            refetch()
          }}
        />

        <DeleteModal
          opened={!!selectedSubscriber}
          orgId={tenantData.id}
          clusterId={tidb.tidbId!}
          subscriber={selectedSubscriber}
          onCancel={() => setSelectedSubscriber(null)}
          onDelete={() => {
            setSelectedSubscriber(null)
            refetch()
          }}
        />
      </Stack>
    )
  }
)

export const AlertsSubscriptionWrapper = observer(() => {
  const [showAddSubscriber, setShowAddSubscriber] = useState(false)
  const {
    store: { tenantData }
  } = useStores()
  const tidb = useSharedTiDBContext()
  const { isLoading, data } = useListNextGenAlertSubscribers(tenantData.id, tidb.tidbId!)
  const { data: quotaData, isLoading: isQuotaLoading } = useGetNextGenAlertSubscriberQuota(tenantData.id, tidb.tidbId!)
  const isOverQuotaLimit = (data?.totalSize || 0) >= (quotaData?.maxAlertSubscribersCount || 0)
  const isCreateDisabled = isLoading || isQuotaLoading || isOverQuotaLimit
  const canUseExternalSubscription = useCanUseExternalSubscription(tenantData.id, tidb.tidbId!)
  const tidbReady = tidb.computed.ready
  const passivePhrase = getTidbStateToPassivePhrase(tidb.state)

  const { accessible, reason: accessDeniedReason } = useAccessDeniedHintReason({
    id: 'TidbxAlertSubscriptionAction'
  })
  const notReadyReason = useMemo<HoverHintReason>(
    () => ({
      id: 'notReady',
      when: !tidbReady,
      content: `This feature is unavailable while the instance is ${passivePhrase}.`
    }),
    [passivePhrase, tidbReady]
  )
  const quotaLimitReason = useMemo<HoverHintReason>(
    () => ({
      id: 'quotaLimit',
      when: isOverQuotaLimit,
      content: (
        <Typography variant="body-md" c="carbon.7">
          The number of created alert subscribers has reached the limit.
          {canUseExternalSubscription ? (
            <>
              {' '}
              If needed, please contact{' '}
              <Anchor
                href="https://docs.pingcap.com/tidbcloud/tidb-cloud-support"
                target="_blank"
                rel="noreferrer"
                data-mp-event="Technical Support Documentation Link Clicked"
                data-mp-source="Alerts"
              >
                technical support
              </Anchor>{' '}
              to adjust the quota.
            </>
          ) : (
            ''
          )}
        </Typography>
      ),
      hoverCardProps: {
        width: 400
      }
    }),
    [canUseExternalSubscription, isOverQuotaLimit]
  )

  return (
    <TiDBPageShell
      title="Alert Subscription"
      headerProps={{
        rightSection: (
          <ReasonHoverHint reasons={[accessDeniedReason, notReadyReason, quotaLimitReason]}>
            <Button
              data-mp-event="Alerts Subscription Subscribe Button Clicked"
              size="sm"
              onClick={() => setShowAddSubscriber(true)}
              disabled={!accessible || !tidbReady || isCreateDisabled}
            >
              Add Subscriber
            </Button>
          </ReasonHoverHint>
        )
      }}
    >
      <AlertsSubscription
        showAddSubscriber={showAddSubscriber}
        closeAddSubscriber={() => setShowAddSubscriber(false)}
      />
    </TiDBPageShell>
  )
})

export default AlertsSubscriptionWrapper
