import { Alert, Anchor, Divider, Group, HoverCard, Paper, Typography } from '@tidbcloud/uikit'
import { FormSelect } from '@tidbcloud/uikit/biz'
import { IconAlertTriangle, IconInfoCircle } from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'
import { useEffect, useMemo } from 'react'
import { useFormContext } from 'react-hook-form'
import { useLocation } from 'react-router-dom'

import { useAccessCheck } from 'dbaas/contexts/access-control'
import {
  useGetTidbCloudProviders,
  useGetTidbCloudRegions
} from 'dbaas/screens/NextGen/my-tidb-creation/shared/premium-byoc/basic-settings/use-cloud-providers-regions'
import {
  ResourcePoolVcpuLimitFeedback,
  ResourcePoolVcpuLimitValidation,
  useResourcePoolVcpuLimitValidation
} from 'dbaas/screens/NextGen/my-tidb-creation/shared/premium-byoc/resource-pool-vcpu-limit'
import { useGetOwnerProjects } from 'dbaas/screens/NextGen/shared/access/use-get-owner-projects'
import { useResourcePoolServiceListResourcePools } from 'dbaas/services/api-clients/v2025/tidb-management/v1beta2'
import {
  Commonv1beta1ServicePlan,
  ResourcePoolServiceListResourcePoolsCloudProvider,
  V1beta2ResourcePoolSummary,
  V1beta2VcpuLimit,
  V1beta2TidbHighAvailabilityType
} from 'dbaas/services/api-clients/v2025/tidb-management/v1beta2/interface'
import useStores from 'dbaas/stores/useStores'

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

import { BasicSettingsSection } from './sections/BasicSettingsSection'
import { CapacitySection } from './sections/CapacitySection/CapacitySection'
import { ByocFormValue } from './types'

interface ByocFormProps {
  formId: string
  planSelector: React.ReactNode
  onSubmit: () => void
  resourcePoolError?: boolean
  onResourcePoolValidationChange: (state: ResourcePoolVcpuLimitValidation) => void
}

const SERVICE_PLAN = Commonv1beta1ServicePlan.BYOC
const SILENT_BYOC_QUERY_REQUEST = { isShowToast: false, isHandleErr: false }
type ResourcePoolSummaryWithHighAvailability = V1beta2ResourcePoolSummary & {
  readonly highAvailabilityType?: V1beta2TidbHighAvailabilityType
  readonly vcpuLimit?: V1beta2VcpuLimit
}
const getResourcePoolId = (pool: V1beta2ResourcePoolSummary) =>
  pool.resourcePoolId ?? pool.name?.split('/').filter(Boolean).pop() ?? ''

const normalizeHighAvailabilityType = (highAvailabilityType?: V1beta2TidbHighAvailabilityType) =>
  highAvailabilityType === V1beta2TidbHighAvailabilityType.ZONAL
    ? V1beta2TidbHighAvailabilityType.ZONAL
    : V1beta2TidbHighAvailabilityType.REGIONAL

export const ByocForm = observer((props: ByocFormProps) => {
  const { formId, planSelector, onSubmit, resourcePoolError, onResourcePoolValidationChange } = props
  const location = useLocation()
  const {
    actions: { fetchUserProfileV2 },
    store: {
      lastVisitLocation: { orgId }
    }
  } = useStores()
  const { watch, getValues, setValue, clearErrors } = useFormContext<ByocFormValue>()

  const projectId = watch('projectId')
  const cloudProvider = watch('cloudProvider')
  const regionId = watch('regionId')
  const resourcePoolId = watch('resourcePoolId')
  const virtualProjectId = useVirtualProjectId()
  const effectiveProjectId = projectId || virtualProjectId
  const canManageResourcePools = useAccessCheck('ByocResourcePoolManagementAction')
  const {
    cloudProviders,
    isLoading: isLoadingProviders,
    isError: isProvidersError
  } = useGetTidbCloudProviders(SERVICE_PLAN, { projectId: effectiveProjectId })
  const {
    regions,
    isLoading: isLoadingRegions,
    isError: isRegionsError
  } = useGetTidbCloudRegions(SERVICE_PLAN, cloudProvider, { projectId: effectiveProjectId })
  const isLoading = isLoadingProviders || isLoadingRegions
  const basicSettingsError = isProvidersError || isRegionsError
  const resourcePoolsQuery = useResourcePoolServiceListResourcePools(
    {
      orgId,
      projectId: effectiveProjectId,
      states: ['ACTIVE'],
      cloudProvider: cloudProvider as ResourcePoolServiceListResourcePoolsCloudProvider,
      regionIds: regionId ? [regionId] : undefined,
      pageSize: 100
    },
    {
      query: {
        enabled: !!orgId && !!effectiveProjectId && !!cloudProvider && !!regionId,
        refetchOnWindowFocus: false,
        retry: 1
      },
      request: SILENT_BYOC_QUERY_REQUEST
    }
  )
  const resourcePoolValidation = useResourcePoolVcpuLimitValidation({
    orgId,
    projectId: effectiveProjectId,
    resourcePoolId
  })
  const resourcePoolOptions = useMemo(
    () =>
      (resourcePoolsQuery.data?.resourcePools ?? [])
        .map((pool) => {
          const resourcePool = pool as ResourcePoolSummaryWithHighAvailability
          const optionResourcePoolId = getResourcePoolId(pool)
          const selectedPoolLimit =
            optionResourcePoolId === resourcePoolId
              ? resourcePoolValidation.resourcePool?.vcpuLimit?.limitedVcpus
              : undefined
          const limitedVcpus = selectedPoolLimit ?? resourcePool.vcpuLimit?.limitedVcpus
          const displayName = pool.displayName ?? optionResourcePoolId
          return {
            label: limitedVcpus ? `${displayName} (Pool vCPU Limit :${limitedVcpus})` : displayName,
            value: optionResourcePoolId,
            highAvailabilityType: resourcePool.highAvailabilityType
          }
        })
        .filter((option) => option.value),
    [resourcePoolId, resourcePoolValidation.resourcePool, resourcePoolsQuery.data?.resourcePools]
  )
  const selectedResourcePoolOption = resourcePoolOptions.find((option) => option.value === resourcePoolId)
  const createResourcePoolHref = `/byoc/resource-pools/new${location.search}`

  const ownerProjects = useGetOwnerProjects()
  const eligibleProjects = useMemo(
    () => ownerProjects.filter((project) => !project.aws_cmek_enabled && project.type === 'tidbx'),
    [ownerProjects]
  )
  const projectOptions = useMemo(
    () => eligibleProjects.map((project) => ({ value: project.id, label: project.name })),
    [eligibleProjects]
  )

  useEffect(() => {
    const nextCloudProvider = cloudProviders?.[0]
    if (!nextCloudProvider) {
      return
    }

    if (!cloudProvider || !cloudProviders.includes(cloudProvider)) {
      setValue('cloudProvider', nextCloudProvider)
    }
  }, [cloudProvider, cloudProviders, setValue])

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

  useEffect(() => {
    if (
      resourcePoolsQuery.isSuccess &&
      resourcePoolId &&
      !resourcePoolOptions.some((option) => option.value === resourcePoolId)
    ) {
      setValue('resourcePoolId', undefined, { shouldValidate: true })
    }
  }, [resourcePoolId, resourcePoolOptions, resourcePoolsQuery.isSuccess, setValue])

  useEffect(() => {
    if (!selectedResourcePoolOption) {
      return
    }

    setValue('highAvailabilityType', normalizeHighAvailabilityType(selectedResourcePoolOption.highAvailabilityType), {
      shouldValidate: true
    })
  }, [selectedResourcePoolOption, setValue])

  useEffect(() => {
    onResourcePoolValidationChange({
      isError: resourcePoolValidation.isError,
      isLimitReached: resourcePoolValidation.isLimitReached,
      isLoading: resourcePoolValidation.isLoading
    })
  }, [
    onResourcePoolValidationChange,
    resourcePoolValidation.isError,
    resourcePoolValidation.isLimitReached,
    resourcePoolValidation.isLoading
  ])

  return (
    <Paper component="form" id={formId} withBorder shadow="none" onSubmit={onSubmit}>
      {planSelector}
      <Divider />
      {basicSettingsError && (
        <Alert color="red" title="Cloud providers and regions could not be loaded" m="lg">
          Refresh the page or try again later.
        </Alert>
      )}
      <BasicSettingsSection
        cloudProviders={cloudProviders}
        regions={regions}
        disabled={isLoading || basicSettingsError}
        projectOptions={projectOptions}
        onProjectCreated={() => fetchUserProfileV2()}
        additionalFields={
          <>
            <FormSelect
              name="resourcePoolId"
              label={
                <Group gap={4} wrap="nowrap">
                  Resource Pool
                  <HoverCard withArrow withinPortal shadow="md">
                    <HoverCard.Target>
                      <IconInfoCircle size={14} c="carbon.7" sx={{ cursor: 'pointer' }} />
                    </HoverCard.Target>
                    <HoverCard.Dropdown maw={320}>
                      <Typography variant="body-sm">
                        A Resource Pool provides the underlying compute, storage, and network resources that can be
                        shared by multiple BYOC instances in the selected region.
                      </Typography>
                    </HoverCard.Dropdown>
                  </HoverCard>
                </Group>
              }
              placeholder="Select a Resource Pool"
              data={resourcePoolOptions}
              disabled={resourcePoolsQuery.isLoading || resourcePoolsQuery.isError || resourcePoolError}
              onChange={(value) => {
                const selectedOption = resourcePoolOptions.find((option) => option.value === value)
                setValue('resourcePoolId', value || undefined, {
                  shouldDirty: true,
                  shouldTouch: true,
                  shouldValidate: true
                })
                if (selectedOption) {
                  setValue('highAvailabilityType', normalizeHighAvailabilityType(selectedOption.highAvailabilityType), {
                    shouldValidate: true
                  })
                }
                if (value) {
                  clearErrors('resourcePoolId')
                }
              }}
            />
            {(resourcePoolsQuery.isError || resourcePoolError) && (
              <Alert color="red" title="Resource pools could not be loaded">
                Refresh the page or try again later.
              </Alert>
            )}
            <Typography variant="body-sm" c="carbon.7">
              {canManageResourcePools && resourcePoolsQuery.isSuccess && resourcePoolOptions.length > 0 && (
                <>
                  Not suitable resource pool? Go to{' '}
                  <Anchor href={createResourcePoolHref} c="peacock.7" fz={12}>
                    Create New Resource Pool
                  </Anchor>
                </>
              )}
              {(!canManageResourcePools || !resourcePoolsQuery.isSuccess || resourcePoolOptions.length === 0) &&
                'Select the shared Resource Pool where this BYOC instance will be deployed.'}
            </Typography>
            <ResourcePoolVcpuLimitFeedback resourcePoolId={resourcePoolId} validation={resourcePoolValidation} />
            {resourcePoolsQuery.isSuccess && resourcePoolOptions.length === 0 && (
              <Alert color="yellow" icon={<IconAlertTriangle size={16} />}>
                {canManageResourcePools ? (
                  <>
                    This region does not have its own resource pool, Please go to{' '}
                    <Anchor href={createResourcePoolHref} c="peacock.7">
                      Create New Resource Pool
                    </Anchor>{' '}
                    first.
                  </>
                ) : (
                  'This region does not have its own resource pool. Please contact your organization owner.'
                )}
              </Alert>
            )}
          </>
        }
      />
      <Divider />
      <CapacitySection projectId={effectiveProjectId} />
    </Paper>
  )
})
