import { zodResolver } from '@hookform/resolvers/zod'
import { notifier } from '@tidbcloud/uikit'
import { observer } from 'mobx-react'
import { useCallback, useId, useState } from 'react'
import { FormProvider, useForm } from 'react-hook-form'
import { useQueryClient } from 'react-query'
import { useLocation } from 'react-router-dom'

import {
  invalidateCapacityLimitsQueries,
  PREMIUM_MAX_RCU_FALLBACK,
  PREMIUM_MIN_RCU,
  useCapacityLimits
} from 'dbaas/screens/NextGen/my-tidb-creation/shared/premium-byoc/capacity/use-capacity-limits'
import {
  DEFAULT_RESOURCE_POOL_VCPU_LIMIT_VALIDATION,
  ResourcePoolVcpuLimitValidation
} from 'dbaas/screens/NextGen/my-tidb-creation/shared/premium-byoc/resource-pool-vcpu-limit'
import { PremiumByocFormValue } from 'dbaas/screens/NextGen/my-tidb-creation/shared/premium-byoc/types'
import { useCreateTidb } from 'dbaas/screens/NextGen/my-tidb-creation/shared/premium-byoc/use-create-tidb'
import { Commonv1beta1ServicePlan } from 'dbaas/services/api-clients/v2025/tidb-management/v1beta2/interface'
import useStores from 'dbaas/stores/useStores'

import { TwoPaneLayout } from '../../layout/TwoPaneLayout'
import { useVirtualProjectId } from '../../shared/use-virtual-project-id'

import { ByocForm } from './ByocForm'
import { ByocSummary } from './ByocSummary'
import { createByocFormSchema } from './schema'

interface ByocCreationProps {
  header: React.ReactNode
  planSelector: React.ReactNode
  active: boolean
}

export const ByocCreation = observer(({ header, planSelector, active }: ByocCreationProps) => {
  const {
    store: {
      lastVisitLocation: { orgId }
    }
  } = useStores()
  const virtualProjectId = useVirtualProjectId()
  const location = useLocation()
  const initialResourcePoolId = new URLSearchParams(location.search).get('resourcePoolId') ?? undefined

  const servicePlan = Commonv1beta1ServicePlan.BYOC
  const formMethods = useForm<PremiumByocFormValue>({
    mode: 'onChange',
    defaultValues: {
      projectId: '',
      cloudProvider: undefined,
      regionId: '',
      resourcePoolId: initialResourcePoolId,
      name: '',
      maxRcu: 20000,
      highAvailabilityType: 'REGIONAL'
    },
    resolver: (values, ctx, options) => {
      const resolvedProjectId = values.projectId || virtualProjectId
      const schema = createByocFormSchema(servicePlan, orgId, resolvedProjectId)
      return zodResolver(schema)(values, ctx, options)
    }
  })
  const { handleSubmit, watch } = formMethods
  const selectedProjectId = watch('projectId')
  const effectiveProjectId = selectedProjectId || virtualProjectId

  const { instanceMaxRcu, availableTotalRcu } = useCapacityLimits({ servicePlan, projectId: effectiveProjectId })
  const effectiveLimit = Math.min(
    instanceMaxRcu ?? PREMIUM_MAX_RCU_FALLBACK,
    availableTotalRcu ?? PREMIUM_MAX_RCU_FALLBACK
  )
  const isQuotaInsufficient = effectiveLimit < PREMIUM_MIN_RCU

  const queryClient = useQueryClient()
  const createMutator = useCreateTidb()
  const [resourcePoolValidation, setResourcePoolValidation] = useState<ResourcePoolVcpuLimitValidation>(
    DEFAULT_RESOURCE_POOL_VCPU_LIMIT_VALIDATION
  )

  const createInstance = useCallback(
    async (data: PremiumByocFormValue) => {
      const resolvedProjectId = data.projectId || virtualProjectId

      if (!resolvedProjectId) {
        notifier.error('Missing organization or project context.')
        return
      }

      const result = await createMutator.mutateAsync({
        data: {
          servicePlan,
          displayName: data.name,
          cloudProvider: data.cloudProvider,
          regionId: data.regionId,
          resourcePoolId: data.resourcePoolId,
          maxRcu: String(data.maxRcu),
          highAvailabilityType: data.highAvailabilityType,
          labels: {
            'tidb.cloud/project': resolvedProjectId
          }
        },
        params: {
          orgId,
          projectId: resolvedProjectId
        }
      })

      // Invalidate capacity limits queries to refresh quota data
      invalidateCapacityLimitsQueries(queryClient, servicePlan, orgId, resolvedProjectId)

      return result
    },
    [createMutator, orgId, queryClient, servicePlan, virtualProjectId]
  )

  const formId = useId()
  const isCreateDisabled =
    isQuotaInsufficient ||
    resourcePoolValidation.isError ||
    resourcePoolValidation.isLimitReached ||
    resourcePoolValidation.isLoading
  const handleValidSubmit = useCallback(
    (data: PremiumByocFormValue) => {
      if (isCreateDisabled) {
        return
      }
      return createInstance(data)
    },
    [createInstance, isCreateDisabled]
  )

  return (
    <FormProvider {...formMethods}>
      <TwoPaneLayout
        visible={active}
        header={header}
        rightSection={
          <ByocSummary
            formId={formId}
            servicePlan={servicePlan}
            disabled={isCreateDisabled}
            isPending={createMutator.isLoading}
          />
        }
      >
        <ByocForm
          formId={formId}
          planSelector={planSelector}
          onSubmit={handleSubmit(handleValidSubmit)}
          onResourcePoolValidationChange={setResourcePoolValidation}
        />
      </TwoPaneLayout>
    </FormProvider>
  )
})
