import { Alert, Button, Divider, Group, Modal, Select, Stack } from '@tidbcloud/uikit'
import { Form, FormPasswordInput, FormSelect, FormTextInput } from '@tidbcloud/uikit/biz'
import { IconInfoCircle, IconXCircle } from '@tidbcloud/uikit/icons'
import { useMemo } from 'react'
import { useForm } from 'react-hook-form'

import { getAlertSubscriberTypeOptions } from 'dbaas/features/AlertSubscription'
import { SharedCluster } from 'dbaas/features/ClusterManagement/cluster'
import { useCreateEssentialAlertSubscriber, useGetEssentialAlertSubscriberQuota } from 'dbaas/services/clinicService'
import {
  EntityAlertSubscriberType,
  EntityCreateAlertSubscriberRequest,
  EntitySupportPlanType
} from 'dbaas/services/clinicService/interface'
import { getErrorMessage } from 'dbaas/services/errorCodes'
import { emailRegEx } from 'dbaas/utils/regex'

interface CreateModalProps {
  orgId: string
  projectId: string
  clusterId: string
  cluster: SharedCluster
  opened: boolean
  onCancel: () => void
  onSuccess: () => void
}

export const CreateModal = (props: CreateModalProps) => {
  const { opened, onCancel } = props
  return (
    <Modal title="Add Subscriber" size={640} centered opened={opened} onClose={onCancel} closeOnClickOutside={false}>
      <CreateForm {...props} />
    </Modal>
  )
}

const FREE_SUBSRIBER_TYPES: string[] = [EntityAlertSubscriberType.EMAIL]

const createDefaultFormValue = (): EntityCreateAlertSubscriberRequest => ({
  dryRun: true,
  name: '',
  subscriberType: EntityAlertSubscriberType.EMAIL,
  email: '',
  slackUrl: '',
  zoomUrl: '',
  zoomToken: '',
  flashDutyUrl: '',
  pagerDutyKey: '',
  webhookUrl: '',
  larkWebhookUrl: '',
  larkSecret: ''
})

const CreateForm = ({ orgId, projectId, clusterId, onCancel, onSuccess }: CreateModalProps) => {
  const form = useForm<EntityCreateAlertSubscriberRequest>({
    mode: 'onBlur',
    reValidateMode: 'onBlur',
    shouldUnregister: true,
    defaultValues: createDefaultFormValue()
  })
  const { watch, resetField } = form
  const watchedFields = watch([
    'subscriberType',
    'email',
    'name',
    'slackUrl',
    'zoomToken',
    'zoomUrl',
    'flashDutyUrl',
    'pagerDutyKey',
    'webhookUrl',
    'larkWebhookUrl',
    'larkSecret'
  ])
  const [subscriberType] = watchedFields

  const { mutateAsync, error, isError, reset, isLoading } = useCreateEssentialAlertSubscriber()
  const { isLoading: isQuotaLoading, data: quotaData } = useGetEssentialAlertSubscriberQuota(
    orgId,
    projectId,
    clusterId
  )
  const canUseExternalSubscription =
    quotaData?.supportPlan === EntitySupportPlanType.Enterprise ||
    quotaData?.supportPlan === EntitySupportPlanType.Premium

  const subscriberTypeSelections = useMemo(() => {
    const subscriberTypes = getAlertSubscriberTypeOptions()
    if (canUseExternalSubscription) {
      return subscriberTypes
    } else {
      return subscriberTypes.map((s) => ({ ...s, disabled: !FREE_SUBSRIBER_TYPES.includes(s.value) }))
    }
  }, [canUseExternalSubscription])

  const resetFieldsWithoutType = () => {
    resetField('name')
    resetField('email')
    resetField('slackUrl')
    resetField('zoomUrl')
    resetField('zoomToken')
    resetField('flashDutyUrl')
    resetField('pagerDutyKey')
    resetField('webhookUrl')
    resetField('larkWebhookUrl')
    resetField('larkSecret')
  }

  return (
    <Form<EntityCreateAlertSubscriberRequest> form={form} withActions={false} onSubmit={() => {}}>
      <Stack mb={8}>
        {!canUseExternalSubscription && (
          <Alert icon={<IconInfoCircle size={12} />} color="peacock">
            The current support plan does not support external subscribers, please upgrade to Premium/Enterprise Plan
            via [Support] in the left navigation bar if needed.
          </Alert>
        )}

        <FormSelect
          name="subscriberType"
          label="Subscriber Type"
          data={subscriberTypeSelections}
          onChange={resetFieldsWithoutType}
          rules={{ required: true }}
          disabled={isQuotaLoading}
        />

        {subscriberType === EntityAlertSubscriberType.EMAIL && <EmailFields />}
        {subscriberType === EntityAlertSubscriberType.ZOOM && <ZoomFields />}
        {subscriberType === EntityAlertSubscriberType.SLACK && <SlackFields />}
        {subscriberType === EntityAlertSubscriberType.FLASHDUTY && <FlashDutyFields />}
        {subscriberType === EntityAlertSubscriberType.PAGERDUTY && <PagerDutyFields />}
        {subscriberType === EntityAlertSubscriberType.WEBHOOK && <WebhookFields />}
        {subscriberType === EntityAlertSubscriberType.LARK && <LarkWebhookFields />}

        <Select
          label="Subscribe Scope"
          value={'Current Essential instance'}
          data={['Current Essential instance']}
          disabled
        />
        {isError && (
          <Alert color="red" icon={<IconXCircle size={14} />}>
            {getErrorMessage(error)}
          </Alert>
        )}
      </Stack>

      <Stack mx="-xl" mb="-xl" pb="md">
        <Divider />
        <Group justify="flex-end" px="xl">
          <Button variant="default" onClick={onCancel}>
            Cancel
          </Button>
          <Button
            disabled={isLoading}
            onClick={() => {
              reset()
              form.handleSubmit(async () => {
                await mutateAsync({ orgId, projectId, clusterId, data: { ...form.getValues(), dryRun: true } })
                await mutateAsync({ orgId, projectId, clusterId, data: { ...form.getValues(), dryRun: false } })
                onSuccess()
              })()
            }}
            data-mp-event="Alerts Subscription Subscriber Save Button Clicked"
          >
            Save
          </Button>
        </Group>
      </Stack>
    </Form>
  )
}

const EmailFields = () => (
  <FormTextInput
    name="email"
    label="Email Address"
    placeholder="Enter subscriber's email"
    rules={{
      required: `Please enter subscriber's email`,
      pattern: {
        value: emailRegEx,
        message: 'Please enter a valid email address'
      }
    }}
  />
)

const nameValidator = (val: string) => {
  const isVali = /^[A-Za-z0-9][-A-Za-z0-9]{2,62}[A-Za-z0-9]$/.test(val)
  if (!isVali) {
    return 'The name must be 4-64 characters that can only include numbers, letters, and hyphens, and the first and last character must be a letter or number.'
  }
  return true
}

const tokenValidator = (val: string) => {
  const isVali = /^[a-zA-Z0-9._-]{1,128}$/.test(val)
  if (!isVali) {
    return 'The token must be 1-128 characters that can only include numbers, letters, hyphens, underscores and dots.'
  }
  return true
}

const ZoomFields = () => (
  <>
    <FormTextInput
      name="name"
      label="Name"
      placeholder="Enter subscriber's name"
      rules={{
        required: `Please enter subscriber's name`,
        validate: nameValidator
      }}
    />
    <FormTextInput
      name="zoomUrl"
      label="URL"
      placeholder="Enter zoom webhook URL"
      rules={{
        required: 'Please enter zoom webhook URL',
        maxLength: { value: 255, message: 'The URL must be less than or equal to 255 characters.' }
      }}
    />
    <FormTextInput
      name="zoomToken"
      label="Token"
      placeholder="Enter zoom token"
      rules={{ required: 'Please enter zoom token', validate: tokenValidator }}
    />
  </>
)

const SlackFields = () => (
  <>
    <FormTextInput
      name="name"
      label="Name"
      placeholder="Enter subscriber's name"
      rules={{ required: `Please enter subscriber's name`, validate: nameValidator }}
    />
    <FormTextInput
      name="slackUrl"
      label="URL"
      placeholder="Enter slack webhook URL"
      rules={{
        required: 'Please enter slack webhook URL',
        maxLength: { value: 255, message: 'The URL must be less than or equal to 255 characters.' }
      }}
    />
  </>
)

const FlashDutyFields = () => (
  <>
    <FormTextInput
      name="name"
      label="Name"
      placeholder="Enter subscriber's name"
      rules={{
        required: `Please enter subscriber's name`,
        validate: nameValidator
      }}
    />
    <FormTextInput
      name="flashDutyUrl"
      label="Webhook URL"
      placeholder="Enter flashduty webhook URL"
      rules={{ required: 'Please enter flashduty webhook URL' }}
    />
  </>
)

const PagerDutyFields = () => (
  <>
    <FormTextInput
      name="name"
      label="Name"
      placeholder="Enter subscriber's name"
      rules={{
        required: `Please enter subscriber's name`,
        validate: nameValidator
      }}
    />
    <FormTextInput
      name="pagerDutyKey"
      label="Integration Key"
      placeholder="Enter pagerduty integration key"
      rules={{ required: 'Please enter pagerduty integration key' }}
    />
  </>
)

const WebhookFields = () => (
  <Stack data-testid="webhook-subscriber-fields">
    <FormTextInput
      name="name"
      label="Name"
      placeholder="Enter subscriber's name"
      rules={{ required: `Please enter subscriber's name`, validate: nameValidator }}
    />
    <FormTextInput
      name="webhookUrl"
      label="Webhook URL"
      placeholder="Enter webhook URL"
      rules={{
        required: 'Please enter webhook URL',
        maxLength: { value: 255, message: 'The URL must be less than or equal to 255 characters.' }
      }}
    />
  </Stack>
)

const LarkWebhookFields = () => (
  <Stack data-testid="lark-webhook-subscriber-fields">
    <FormTextInput
      name="name"
      label="Name"
      placeholder="Enter subscriber's name"
      rules={{ required: `Please enter subscriber's name`, validate: nameValidator }}
    />
    <FormTextInput
      name="larkWebhookUrl"
      label="Webhook URL"
      placeholder="Enter Lark webhook URL"
      rules={{
        required: 'Please enter Lark webhook URL',
        maxLength: { value: 255, message: 'The URL must be less than or equal to 255 characters.' }
      }}
    />
    <FormPasswordInput
      name="larkSecret"
      label="Secret"
      type="password"
      placeholder="Enter Lark secret"
      rules={{ required: 'Please enter Lark secret' }}
    />
  </Stack>
)
