import { zodResolver } from '@hookform/resolvers/zod'
import { Divider } from '@tidbcloud/uikit'
import { Form } from '@tidbcloud/uikit/biz'
import { useDisclosure } from '@tidbcloud/uikit/hooks'
import { useEffect } from 'react'
import { useForm } from 'react-hook-form'
import { z } from 'zod'

import { CloudProviderConst } from 'dbaas/features/Project'
import { useCancel } from 'dbaas/screens/ClustersV2/new/Wrapper/helpers'
import {
  Serverlessv1beta1ClusterHighAvailabilityType,
  V1beta1ClusterAutoScaling,
  Commonv1beta1ServicePlan
} from 'dbaas/services/api-clients/v2023/serverless/v1beta1/interface'

import { ClusterName } from '../components/ClusterName'
import { ClusterPlan, ClusterPlanProps } from '../components/ClusterPlan'
import { Encryption } from '../components/Encryption'
import { BaseTiDBNextGenFormValue, BaseTiDBNextGenFormValueSchema } from '../components/helper'
import { Layout } from '../components/Layout'
import { ProviderRegion } from '../components/ProviderRegion'
import { SwitchGenModal } from '../components/SwitchGenModal'

import { Capacity } from './Capacity'
import { EssentialSummaryCard } from './EssentialSummary'
import { ESSENTIAL_RCU_MAX, ESSENTIAL_RCU_MIN, ESSENTIAL_RCU_STEP, useEssentialFormStore } from './helper'
import { HighAvailability } from './HighAvailability'

export interface EssentialFormValue extends BaseTiDBNextGenFormValue {
  encrypted: boolean
  highAvailabilityType: Serverlessv1beta1ClusterHighAvailabilityType
  autoScaling?: V1beta1ClusterAutoScaling
}

type EssentialProps = {
  onChange?: (plan: Commonv1beta1ServicePlan) => void
  onGenChange?: () => void
  clusterPlanProps?: Omit<ClusterPlanProps, 'value' | 'onChange'>
}

export const Essential = ({ onChange, onGenChange, clusterPlanProps }: EssentialProps) => {
  const methods = useForm<EssentialFormValue>({
    mode: 'onChange',
    defaultValues: {
      servicePlan: Commonv1beta1ServicePlan.Essential,
      provider: '',
      region: '',
      name: '',
      encrypted: true,
      autoScaling: {
        minRcu: ESSENTIAL_RCU_MIN,
        maxRcu: 10000
      },
      highAvailabilityType: Serverlessv1beta1ClusterHighAvailabilityType.REGIONAL
    },
    resolver: async (data, context, options) => {
      const schema = BaseTiDBNextGenFormValueSchema.extend({
        encrypted: z.boolean(),
        autoScaling: z
          .object({
            minRcu: z
              .number()
              .int()
              .multipleOf(ESSENTIAL_RCU_STEP)
              .min(ESSENTIAL_RCU_MIN, `Min RCUs should be greater than ${ESSENTIAL_RCU_MIN}`)
              .max(ESSENTIAL_RCU_MAX, `Max RCUs should be less than ${ESSENTIAL_RCU_MAX}`),
            maxRcu: z
              .number()
              .int()
              .multipleOf(ESSENTIAL_RCU_STEP)
              .min(ESSENTIAL_RCU_MIN, `Min RCUs should be greater than ${ESSENTIAL_RCU_MIN}`)
              .max(ESSENTIAL_RCU_MAX, `Max RCUs should be less than ${ESSENTIAL_RCU_MAX}`)
          })
          .refine(
            (data) => {
              return data.minRcu <= data.maxRcu
            },
            {
              message: 'Min RCUs should be less than or equal to Max RCUs',
              path: ['minRcu']
            }
          )
          .refine(
            (data) => {
              return data.minRcu <= data.maxRcu
            },
            {
              message: 'Max RCUs should be greater than or equal to Min RCUs',
              path: ['maxRcu']
            }
          ),
        highAvailabilityType: z
          .enum([
            Serverlessv1beta1ClusterHighAvailabilityType.REGIONAL,
            Serverlessv1beta1ClusterHighAvailabilityType.ZONAL
          ])
          .optional()
      })
      return zodResolver(schema)(data, context, options)
    }
  })
  const cancel = useCancel()

  const { watch, setValue } = methods
  const provider = watch('provider')

  const { name, providers, regions, isLoading } = useEssentialFormStore(provider, 'Essential')

  useEffect(() => {
    if (name) {
      setValue('name', name)
    }
  }, [name, setValue])

  useEffect(() => {
    setValue('provider', CloudProviderConst.ALICLOUD)
  }, [providers, setValue])

  useEffect(() => {
    setValue('region', regions[0]?.name ?? '')
  }, [regions, setValue])

  const [modalOpened, modalHandlers] = useDisclosure(false)

  useEffect(() => {
    if (provider === CloudProviderConst.AWS) {
      modalHandlers.open()
    }
  }, [modalHandlers, provider])

  return (
    <Form form={methods} withActions={false} formMode="onChange" onSubmit={() => {}}>
      <Layout
        leftSection={
          <>
            <ClusterPlan value={Commonv1beta1ServicePlan.Essential} onChange={onChange} {...clusterPlanProps} />
            <Divider />
            <ProviderRegion providers={providers} regions={regions} disabled={isLoading} />
            <Divider />
            <ClusterName disabled={isLoading} />
            <Divider />
            <Capacity />
            <Divider />
            <Encryption />
            <Divider />
            <HighAvailability />
          </>
        }
        rightSection={<EssentialSummaryCard onCancel={cancel} />}
      />
      <SwitchGenModal
        opened={modalOpened}
        switchingProvider={CloudProviderConst.AWS}
        onConfirm={() => {
          onGenChange?.()
          modalHandlers.close()
        }}
        onCancel={() => {
          setValue('provider', CloudProviderConst.ALICLOUD)
          modalHandlers.close()
        }}
      />
    </Form>
  )
}
