import { Alert, Stack, Typography } from '@tidbcloud/uikit'
import { FormSelect, FormTextInput } from '@tidbcloud/uikit/biz'
import { IconAlertCircle } from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'
import { useEffect, useMemo } from 'react'
import { useFormContext } from 'react-hook-form'

import { getCloudProviderLabel } from 'dbaas/features/Project'
import { useServerlessServiceListRegions } from 'dbaas/services/api-clients/v2023/serverless/v1beta1'

import { ClaimFormValue, ClaimSelectOption } from './types'

const FTS_DOCS_URL = 'https://docs.pingcap.com/ai/vector-search-full-text-search-sql/#get-started'
const AUTO_EMBEDDING_DOCS_URL = 'https://docs.pingcap.com/ai/vector-search-auto-embedding-overview/'

interface ClaimFormProps {
  formId: string
  onSubmit: () => void
  orgOptions: ClaimSelectOption[]
  projectOptionsByOrg: Record<string, ClaimSelectOption[]>
  isScopeLoading: boolean
  onOrgChange?: (orgId: string) => void
  onProjectChange?: (projectId: string) => void
}

export const ClaimForm = observer(
  ({
    formId,
    onSubmit,
    orgOptions,
    projectOptionsByOrg,
    isScopeLoading,
    onOrgChange,
    onProjectChange
  }: ClaimFormProps) => {
    const { watch, getValues, setValue, setError, clearErrors } = useFormContext<ClaimFormValue>()
    const orgId = watch('orgId')
    const provider = watch('provider')
    const projectId = watch('projectId')

    const query = useServerlessServiceListRegions(
      { orgId, servicePlan: 'Starter' },
      {
        query: {
          enabled: !!orgId,
          refetchOnWindowFocus: false,
          select: (data) => data?.regions
        }
      }
    )
    const regionsData = query.data

    const cloudProviders = useMemo(
      () => Array.from(new Set<string>(regionsData?.map((item) => item?.cloudProvider || ''))).filter(Boolean),
      [regionsData]
    )

    const regions = useMemo(
      () =>
        regionsData?.filter(
          (item) => item?.cloudProvider === provider && !!(item?.name && item?.displayName && item?.cloudProvider)
        ) ?? [],
      [regionsData, provider]
    )

    const projectOptions = useMemo(() => projectOptionsByOrg[orgId] || [], [projectOptionsByOrg, orgId])

    // ---- auto-select org/project ----

    useEffect(() => {
      if (isScopeLoading) {
        return
      }
      if (!orgOptions.length) {
        setError('orgId', {
          type: 'manual',
          message: 'No organization available for your account.'
        })
        return
      }

      clearErrors('orgId')
      const isCurrentValid = !!orgId && orgOptions.some((org) => org.value === orgId)
      if (!isCurrentValid) {
        setValue('orgId', orgOptions[0].value, { shouldValidate: true })
      }
    }, [isScopeLoading, orgOptions, orgId, setValue, setError, clearErrors])

    useEffect(() => {
      if (isScopeLoading) {
        return
      }
      if (!orgId) {
        if (projectId) {
          setValue('projectId', '', { shouldValidate: true })
        }
        clearErrors('projectId')
        return
      }
      if (!projectOptions.length) {
        if (projectId) {
          setValue('projectId', '', { shouldValidate: true })
        }
        setError('projectId', {
          type: 'manual',
          message: 'No project available in selected organization.'
        })
        return
      }

      clearErrors('projectId')
      const isCurrentValid = !!projectId && projectOptions.some((p) => p.value === projectId)
      if (!isCurrentValid) {
        setValue('projectId', projectOptions[0].value, { shouldValidate: true })
      }
    }, [isScopeLoading, orgId, projectOptions, projectId, setValue, setError, clearErrors])

    useEffect(() => {
      const nextProvider = cloudProviders[0]
      if (nextProvider && (!provider || !cloudProviders.includes(provider))) {
        setValue('provider', nextProvider)
      }
    }, [provider, cloudProviders, setValue])

    useEffect(() => {
      const currentRegion = getValues('region')
      const nextRegion = regions?.[0]?.name ?? ''
      if (!currentRegion || !regions?.some((r) => r.name === currentRegion)) {
        setValue('region', nextRegion)
      }
    }, [regions, setValue, getValues])

    // ---- render ----

    const providerData = useMemo(
      () => cloudProviders.map((p) => ({ value: p, label: getCloudProviderLabel(p) || p })),
      [cloudProviders]
    )
    const regionData = useMemo(() => regions.map((r) => ({ value: r.name!, label: r.displayName! })), [regions])

    return (
      <form id={formId} onSubmit={onSubmit}>
        <Typography variant="body-lg" c="carbon.7">
          Welcome to TiDB Cloud!
        </Typography>
        <Typography fz={24} fw={700} mt={4}>
          Choose where to save your database.
        </Typography>

        <Stack gap="md" mt="xl">
          <FormSelect
            name="orgId"
            label="Organization"
            disabled={isScopeLoading || orgOptions.length <= 1}
            data={orgOptions}
            onChange={(value) => {
              if (value) {
                onOrgChange?.(value)
              }
            }}
            data-testid="claim-form-org-select"
          />
          <FormSelect
            name="projectId"
            label="Project"
            disabled={isScopeLoading || !orgId || !projectOptions.length}
            data={projectOptions}
            onChange={(value) => {
              if (value) {
                onProjectChange?.(value)
              }
            }}
            data-testid="claim-form-project-select"
          />
          <FormSelect
            name="provider"
            label="Cloud Provider"
            disabled={providerData.length <= 1 || isScopeLoading}
            data={providerData}
          />
          <FormSelect
            name="region"
            label="Region"
            disabled={regionData.length <= 1 || isScopeLoading}
            data={regionData}
          />
          <Alert color="peacock" icon={<IconAlertCircle size={14} />} data-testid="claim-form-ai-search-alert">
            AI search support varies by cloud provider and region. If you are using features like FTS, Auto Embedding,
            or embedding SQL functions, check the{' '}
            <a href={FTS_DOCS_URL} target="_blank" rel="noopener noreferrer">
              FTS documentation
            </a>{' '}
            and{' '}
            <a href={AUTO_EMBEDDING_DOCS_URL} target="_blank" rel="noopener noreferrer">
              Auto Embedding documentation
            </a>{' '}
            before claiming.
          </Alert>
        </Stack>

        <Typography fz={18} fw={700} mt="xl">
          Instance Name
        </Typography>
        <FormTextInput
          name="name"
          placeholder="Enter your instance name"
          disabled={isScopeLoading}
          mt="sm"
          description={
            <span>
              Your database will be saved as a TiDB Cloud Starter instance.{' '}
              <a
                href="https://docs.pingcap.com/tidbcloud/select-cluster-tier#tidb-cloud-starter"
                target="_blank"
                rel="noopener noreferrer"
              >
                Learn more about the Starter plan.
              </a>
            </span>
          }
        />
      </form>
    )
  }
)
