import { zodResolver } from '@hookform/resolvers/zod'
import { notifier } from '@tidbcloud/uikit'
import { observer } from 'mobx-react'
import { useCallback, useId } from 'react'
import { FormProvider, useForm, useFormContext, type FieldErrors, type Path } from 'react-hook-form'
import { useHistory, useLocation } from 'react-router-dom'

import { TIDBS_NEW_DEDICATED_CREATION_SOURCE } from 'dbaas/features/ClusterManagement/dedicated/creation/CreationAlert'
import { markOneConsoleFeedbackEventCompleted } from 'dbaas/layouts/v5/NewNavGuide/feedbackState'
import { CreationStoreProvider, useCreationStore } from 'dbaas/screens/ClustersV2/new/store'
import useStores from 'dbaas/stores/useStores'
import { eventTracking } from 'dbaas/utils/tracking'

import { TwoPaneLayout } from '../../layout/TwoPaneLayout'
import { findFirstVisibleFormError } from '../../shared/form-errors'

import { DedicatedForm } from './DedicatedForm'
import { DedicatedSummary } from './DedicatedSummary'
import { useCreateDedicated } from './hooks/use-dedicated-create'
import { useSetUpRegionalCidr } from './hooks/use-setup-regional-cidr'
import { dedicatedFormSchema } from './schema'
import { DedicatedCreationFormValue } from './types'

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

const DedicatedCreationContent = observer(
  ({
    header,
    planSelector,
    active,
    formId,
    orgId,
    projectId,
    onSuccess
  }: DedicatedCreationProps & {
    formId: string
    orgId: string
    projectId: string
    onSuccess: () => void
  }) => {
    const { handleSubmit, setFocus, setError } = useFormContext<DedicatedCreationFormValue>()
    const { dedicated: creationStore } = useCreationStore()

    const cidrConfiguredStatus = creationStore?.cidrConfigured
    const cidrConfigured = cidrConfiguredStatus === true

    const { setUpRegionalCidr, isLoading: isSettingCidr } = useSetUpRegionalCidr({
      orgId,
      projectId,
      configured: cidrConfigured,
      onError: (errMsg) => {
        if (errMsg) {
          notifier.error(<div dangerouslySetInnerHTML={{ __html: errMsg }} />)
        }
      }
    })

    const { createCluster, isCreating } = useCreateDedicated({
      orgId,
      projectId,
      onSuccess: () => onSuccess(),
      onError: (errMsg) => notifier.error(<div dangerouslySetInnerHTML={{ __html: errMsg }} />)
    })

    const onValidSubmit = useCallback(
      async (data: DedicatedCreationFormValue) => {
        const { provider, region, sizes, name, port, projectCIDR } = data.dedicated

        if (typeof cidrConfiguredStatus === 'undefined') {
          notifier.error('Project CIDR is still loading. Please try again in a moment.')
          return
        }

        const normalizedProjectCIDR = projectCIDR?.trim() ?? ''
        if (!cidrConfigured && !normalizedProjectCIDR) {
          setError('dedicated.projectCIDR', { type: 'manual', message: 'Please enter a valid CIDR.' })
          setFocus('dedicated.projectCIDR', { shouldSelect: true })
          return
        }

        const cidrErrMsg = await setUpRegionalCidr({ provider, region, cidr: normalizedProjectCIDR })
        if (cidrErrMsg) {
          return
        }

        await createCluster({ provider, region, sizes, name, port })
      },
      [cidrConfigured, cidrConfiguredStatus, createCluster, setError, setFocus, setUpRegionalCidr]
    )

    const onInvalidSubmit = useCallback(
      (formErrors: FieldErrors<DedicatedCreationFormValue>) => {
        const hiddenErrorPaths = cidrConfigured ? new Set(['dedicated.projectCIDR']) : new Set<string>()
        const firstVisibleError = findFirstVisibleFormError(formErrors, { skippedPaths: hiddenErrorPaths })

        if (firstVisibleError?.path) {
          setFocus(firstVisibleError.path as Path<DedicatedCreationFormValue>, { shouldSelect: true })
          return
        }

        const fallbackError = findFirstVisibleFormError(formErrors)
        notifier.error(fallbackError?.message ?? 'Please complete required fields before creating.')
      },
      [cidrConfigured, setFocus]
    )

    return (
      <TwoPaneLayout
        visible={active}
        header={header}
        rightSection={<DedicatedSummary formId={formId} isPending={isCreating || isSettingCidr} />}
      >
        <DedicatedForm
          formId={formId}
          planSelector={planSelector}
          onSubmit={handleSubmit(onValidSubmit, onInvalidSubmit)}
        />
      </TwoPaneLayout>
    )
  }
)

export const DedicatedCreation = observer(({ header, planSelector, active }: DedicatedCreationProps) => {
  const history = useHistory()
  const location = useLocation()
  const formId = useId()
  const {
    store: {
      userProfile: { id: userId },
      lastVisitLocation: { orgId, projectId }
    },
    actions: { refreshOrgData }
  } = useStores()

  const onSuccess = useCallback(() => {
    refreshOrgData()
    eventTracking('Created A Cluster', {
      'Cluster Type': 'Dedicated Tier',
      source: 'Clusters - Creation v2'
    })
    markOneConsoleFeedbackEventCompleted(userId, 'creation')
    notifier.success('Creating Dedicated Cluster...')
    history.push(`/tidbs${location.search}`, {
      from: TIDBS_NEW_DEDICATED_CREATION_SOURCE
    })
  }, [history, location.search, refreshOrgData, userId])

  const formMethods = useForm<DedicatedCreationFormValue>({
    mode: 'onChange',
    defaultValues: {
      initializing: { dedicated: 'false' },
      dedicated: {
        provider: '',
        region: '',
        cmekId: undefined,
        name: '',
        port: 4000,
        specVersion: 'V2',
        sizes: {
          tidb: { replicas: 2, profileName: '', storageGiB: 0 },
          tikv: { replicas: 3, profileName: '', storageGiB: 0 },
          tiflash: { replicas: 0, profileName: '', storageGiB: 0 }
        },
        projectCIDR: undefined
      }
    },
    resolver: zodResolver(dedicatedFormSchema)
  })

  return (
    <FormProvider {...formMethods}>
      <CreationStoreProvider>
        <DedicatedCreationContent
          header={header}
          planSelector={planSelector}
          active={active}
          formId={formId}
          orgId={orgId}
          projectId={projectId}
          onSuccess={onSuccess}
        />
      </CreationStoreProvider>
    </FormProvider>
  )
})
