import {
  Alert,
  Anchor,
  Button,
  Divider,
  Group,
  Input,
  Loader,
  notifier,
  Paper,
  Stack,
  TextInput,
  Typography
} from '@tidbcloud/uikit'
import { DateTimePicker, FormErrorMessage, FormRadioGroup, FormSelect, useDateTimePicker } from '@tidbcloud/uikit/biz'
import { IconAlertTriangle } from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'
import { useEffect, useId, useMemo } from 'react'
import { FormProvider, useForm, useFormContext } from 'react-hook-form'
import { useHistory, useLocation, useParams } from 'react-router-dom'

import { HeroComponent, isHeroQueryReady } from 'dbaas/components/Measurement'
import TimeComponent from 'dbaas/components/TimeComponent'
import { PageAccessGuard, useAccessCheck } from 'dbaas/contexts/access-control'
import { useOrgProjectClusterIds } from 'dbaas/features/Common'
import { getCloudProviderLabel } from 'dbaas/features/Project'
import { queryClient } from 'dbaas/reactQueryClient'
import { BasicSettingsSection as ByocBasicSettingsSection } from 'dbaas/screens/NextGen/my-tidb-creation/plans/byoc/sections/BasicSettingsSection'
import { CapacitySection as ByocCapacitySection } from 'dbaas/screens/NextGen/my-tidb-creation/plans/byoc/sections/CapacitySection/CapacitySection'
import { DualLayerDataEncryptionSection as ByocDualLayerDataEncryptionSection } from 'dbaas/screens/NextGen/my-tidb-creation/plans/byoc/sections/DualLayerDataEncryptionSection'
import { ByocCost } from 'dbaas/screens/NextGen/my-tidb-creation/plans/byoc/summary/ByocCost'
import { filterEssentialRegionsByServicePlan } from 'dbaas/screens/NextGen/my-tidb-creation/plans/essential/essential-regions'
import { ESSENTIAL_V2_RCU_MIN } from 'dbaas/screens/NextGen/my-tidb-creation/plans/EssentialV2/schema'
import { HighAvailabilitySection as EssentialV2HighAvailabilitySection } from 'dbaas/screens/NextGen/my-tidb-creation/plans/EssentialV2/sections/HighAvailabilitySection'
import { EssentialV2Cost } from 'dbaas/screens/NextGen/my-tidb-creation/plans/EssentialV2/summary/EssentialV2Cost'
import { BasicSettingsSection as PremiumBasicSettingsSection } from 'dbaas/screens/NextGen/my-tidb-creation/plans/premium/sections/BasicSettingsSection'
import { CapacitySection as PremiumCapacitySection } from 'dbaas/screens/NextGen/my-tidb-creation/plans/premium/sections/CapacitySection'
import { DualLayerDataEncryptionSection as PremiumDualLayerDataEncryptionSection } from 'dbaas/screens/NextGen/my-tidb-creation/plans/premium/sections/DualLayerDataEncryptionSection'
import { HighAvailabilitySection as PremiumHighAvailabilitySection } from 'dbaas/screens/NextGen/my-tidb-creation/plans/premium/sections/HighAvailabilitySection'
import { CapacitySection as PremiumReservedCapacitySection } from 'dbaas/screens/NextGen/my-tidb-creation/plans/premium-reserved/sections/CapacitySection'
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 { useDualLayerDataEncryptionFeatEnabled } from 'dbaas/screens/NextGen/my-tidb-creation/shared/premium-byoc/dual-layer-data-encryption/use-dual-layer-data-encryption-feat-enabled'
import {
  ResourcePoolVcpuLimitFeedback,
  ResourcePoolVcpuLimitValidation,
  useResourcePoolVcpuLimitValidation
} 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 { useVirtualProjectId } from 'dbaas/screens/NextGen/my-tidb-creation/shared/use-virtual-project-id'
import { useCreateResourceRoleState } from 'dbaas/screens/NextGen/shared/access/create-resource-role'
import { useSharedTiDBContextSafe } from 'dbaas/screens/NextGen/tidb-mgmt-container/shared/tidb-context'
import { FormSection } from 'dbaas/screens/Restore/FormSection'
import { RestoreLayout } from 'dbaas/screens/Restore/RestoreLayout'
import { RestoreSummaryCard, RestoreSummaryItem, RestoreSummarySection } from 'dbaas/screens/Restore/RestoreSummary'
import {
  useBackupServiceListDeletedTidbs,
  useRegionServiceListRegions,
  useResourcePoolServiceListResourcePools,
  useTidbServiceGetBackupSetting,
  useTidbServiceListTidbBackups,
  useTidbServiceRestoreTidb
} from 'dbaas/services/api-clients/v2025/tidb-management/v1beta2'
import {
  Commonv1beta1Region,
  Commonv1beta1ServicePlan,
  Nextgenv1beta2Backup,
  Nextgenv1beta2RestoreMode,
  ResourcePoolServiceListResourcePoolsCloudProvider,
  V1beta1RegionCloudProvider,
  V1beta2DeletedTidb,
  V1beta2ResourcePoolSummary,
  V1beta2VcpuLimit,
  V1beta2TidbDualLayerDataEncryption,
  V1beta2TidbHighAvailabilityType
} from 'dbaas/services/api-clients/v2025/tidb-management/v1beta2/interface'
import { getErrorMessage } from 'dbaas/services/errorCodes'
import useStores from 'dbaas/stores/useStores'
import { formatTime } from 'dbaas/utils/format'

import { PremiumPricingCost } from '../../my-tidb-creation/plans/premium/summary/PremiumPricingCost'
import { PremiumReservedPricingCost } from '../../my-tidb-creation/plans/premium-reserved/summary/PremiumReservedPricingCost'

import { EssentialV2RestoreCapacitySection } from './EssentialV2RestoreCapacitySection'
import { getBackupSnapshotOption } from './getBackupSnapshotOption'

type RestoreTargetFormData = PremiumByocFormValue & {
  backupId?: string
  pointInTime?: string
  restoreMode: Nextgenv1beta2RestoreMode
  backup?: Nextgenv1beta2Backup
  resourcePoolId?: string
}

/**
 * This state should be accessible when navigating from recycle-bin or backup list page via history.push(..., { state: { backup, tidb } })
 * Note that state.backup and state.tidb exists when from recycle-bin page
 * Only state backup exist when from backup list page's backup item
 * Both state.backup and state.tidb WILL NOT exist when from backup list page's header restore button
 */
interface HistoryState {
  backup?: Nextgenv1beta2Backup
  tidb?: V1beta2DeletedTidb
}

const PREMIUM_RESERVED_PLAN = 'Premium_Reserved'
const getResourcePoolId = (pool: V1beta2ResourcePoolSummary) =>
  pool.resourcePoolId ?? pool.name?.split('/').filter(Boolean).pop() ?? ''
type ResourcePoolSummaryWithVcpuLimit = V1beta2ResourcePoolSummary & {
  readonly vcpuLimit?: V1beta2VcpuLimit
}
const SILENT_BYOC_QUERY_REQUEST = { isShowToast: false, isHandleErr: false }

const isPremiumReservedPlan = (servicePlan?: Commonv1beta1ServicePlan | string) => {
  return String(servicePlan) === PREMIUM_RESERVED_PLAN
}

const getRestorePlanLabel = (servicePlan: Commonv1beta1ServicePlan) => {
  if (servicePlan === Commonv1beta1ServicePlan.BYOC) {
    return 'BYOC'
  }

  if (servicePlan === Commonv1beta1ServicePlan.Essential_V2) {
    return 'Essential'
  }

  if (isPremiumReservedPlan(servicePlan)) {
    return 'Premium Reserved'
  }

  return 'Premium'
}

const getDualLayerDataEncryptionValue = (value?: V1beta2TidbDualLayerDataEncryption) => {
  if (!value || value.noEncryption) {
    return {
      encrypted: false,
      keyType: 'service-managed' as const,
      awsCmek: {
        accountId: '',
        kmsKeyArn: ''
      }
    }
  }

  if (value.cmek) {
    return {
      encrypted: true,
      keyType: 'customer-managed' as const,
      awsCmek: {
        accountId: value.cmek.awsPrincipal?.accountId ?? '',
        kmsKeyArn: value.cmek.awsKms?.kmsKeyArn ?? ''
      }
    }
  }

  return {
    encrypted: true,
    keyType: 'service-managed' as const,
    awsCmek: {
      accountId: '',
      kmsKeyArn: ''
    }
  }
}

const RestoreSelectionSection = observer(
  ({ state, servicePlan }: { state?: HistoryState; servicePlan: Commonv1beta1ServicePlan }) => {
    const {
      store: { tenantData }
    } = useStores()
    const methods = useFormContext<RestoreTargetFormData>()
    const { id: tidbId } = useParams<{ id: string }>()
    const { orgId, projectId } = useOrgProjectClusterIds()
    const tidbInContext = useSharedTiDBContextSafe()
    const tidb = state?.tidb ?? tidbInContext
    const fromRecycleBin = !!(state?.backup && state?.tidb)

    const {
      data: backupListData,
      isLoading,
      isFetched,
      isError
    } = useTidbServiceListTidbBackups(
      tidbId,
      { orgId, projectId, pageSize: 1000, states: ['SUCCEEDED'] },
      {
        query: {
          enabled: !fromRecycleBin
        }
      }
    )

    const { data: backupSettingData, isLoading: isLoadingBackupSetting } = useTidbServiceGetBackupSetting(
      tidbId,
      { orgId, projectId },
      {
        query: {
          refetchOnWindowFocus: false,
          enabled: !fromRecycleBin
        }
      }
    )

    const pointInTime = methods.watch('pointInTime')
    const restoreMode = methods.watch('restoreMode')
    const [pitrStartDate, pitrEndDate] = useMemo(() => {
      const start = state?.tidb?.pitrStartTime ?? backupSettingData?.pitrStartTime
      const end = state?.tidb?.pitrEndTime ?? backupSettingData?.pitrEndTime
      let startDate = start ? new Date(start) : undefined

      if (startDate) {
        const ceilStartTs = Math.ceil(startDate.getTime() / 1000) * 1000
        startDate = new Date(ceilStartTs)
      }

      return [startDate, end ? new Date(end) : undefined]
    }, [
      backupSettingData?.pitrEndTime,
      backupSettingData?.pitrStartTime,
      state?.tidb?.pitrEndTime,
      state?.tidb?.pitrStartTime
    ])

    const dateTimePickerProps = useDateTimePicker({
      startDate: pitrStartDate,
      endDate: pitrEndDate,
      value: pointInTime ? new Date(pointInTime) : pitrEndDate,
      utcOffset: tenantData.timezone,
      onChange: (val) => methods.setValue('pointInTime', new Date(val).toISOString()),
      formatter: (val) =>
        formatTime(val, {
          offset: tenantData.timezone,
          showSeconds: true,
          showTimezone: true
        })
    })

    const backupList = useMemo(() => {
      return fromRecycleBin ? [state?.backup!] : (backupListData?.backups ?? [])
    }, [backupListData?.backups, fromRecycleBin, state?.backup])

    const snapshotOptions = useMemo(() => {
      const options = backupList.map((item) => getBackupSnapshotOption(item, tenantData.timezone))

      if (state?.backup?.id && options.findIndex((item) => item.value === state.backup?.id) === -1) {
        options.unshift(getBackupSnapshotOption(state.backup, tenantData.timezone))
      }

      return options
    }, [backupList, state?.backup, tenantData.timezone])

    const planLabel = getRestorePlanLabel(servicePlan)

    return (
      <FormSection label="Select Backup" description="Confirm the backup data you want to restore.">
        <HeroComponent ready={fromRecycleBin || isHeroQueryReady({ isFetched, isError })} />
        <Stack gap="md">
          <TextInput label={`Your ${planLabel} Instance`} disabled value={tidb?.displayName ?? ''} />

          <FormRadioGroup
            label="Restore Mode"
            name="restoreMode"
            data={[
              { label: 'Snapshot Restore', value: Nextgenv1beta2RestoreMode.SNAPSHOT },
              { label: 'Point-in-Time Restore', value: Nextgenv1beta2RestoreMode.PITR }
            ]}
            onChange={(value) => {
              if (value === Nextgenv1beta2RestoreMode.PITR && !pointInTime) {
                if (pitrEndDate) {
                  methods.setValue('pointInTime', pitrEndDate.toISOString())
                } else if (pitrStartDate) {
                  methods.setValue('pointInTime', pitrStartDate.toISOString())
                }
              }
            }}
          />

          {restoreMode === Nextgenv1beta2RestoreMode.SNAPSHOT && (
            <FormSelect
              name="backupId"
              label="Backup Snapshot"
              data={snapshotOptions}
              searchable
              placeholder="Select a snapshot backup"
              rules={{ required: 'Required' }}
              rightSection={isLoading ? <Loader size="sm" /> : null}
              onChange={(value) => {
                methods.setValue(
                  'backup',
                  backupList.find((item) => item.id === value)
                )
              }}
            />
          )}

          {restoreMode === Nextgenv1beta2RestoreMode.PITR && (
            <div>
              <Input.Label mb={5}>Restore to</Input.Label>
              <DateTimePicker
                {...dateTimePickerProps}
                loading={isLoadingBackupSetting}
                footer={
                  pitrStartDate &&
                  pitrEndDate && (
                    <Stack gap={4}>
                      <Typography c="carbon.7" variant="body-lg">
                        Pick any time within the PITR window:
                      </Typography>
                      <Typography c="carbon.7" variant="body-lg">
                        From <TimeComponent time={pitrStartDate} /> to <TimeComponent time={pitrEndDate} />.
                      </Typography>
                    </Stack>
                  )
                }
              />
            </div>
          )}
        </Stack>
      </FormSection>
    )
  }
)

const DestinationConfigSection = ({
  servicePlan,
  regions,
  projectOptions,
  effectiveProjectId,
  projectOptional,
  onProjectCreated,
  isDataEncryptionFeatEnabled,
  defaultReservedCapacityTemplateId,
  resourcePoolOptions,
  resourcePoolValidation,
  isResourcePoolsLoading,
  isResourcePoolsError
}: {
  servicePlan: Commonv1beta1ServicePlan
  regions: Commonv1beta1Region[]
  projectOptions: { value: string; label: string }[]
  effectiveProjectId: string
  projectOptional: boolean
  onProjectCreated: () => void
  isDataEncryptionFeatEnabled: boolean
  defaultReservedCapacityTemplateId?: string
  resourcePoolOptions: { value: string; label: string }[]
  resourcePoolValidation: ResourcePoolVcpuLimitValidation
  isResourcePoolsLoading: boolean
  isResourcePoolsError: boolean
}) => {
  const location = useLocation()
  const methods = useFormContext<RestoreTargetFormData>()
  const cloudProvider = methods.watch('cloudProvider')!
  const regionId = methods.watch('regionId')
  const resourcePoolId = methods.watch('resourcePoolId')
  const planLabel = getRestorePlanLabel(servicePlan)
  const createResourcePoolHref = `/byoc/resource-pools/new${location.search}`
  const canManageResourcePools = useAccessCheck('ByocResourcePoolManagementAction')

  return (
    <>
      <Stack gap={4} p="xl" pb={0}>
        <Typography variant="title-lg" fz={20}>
          Restore to a New {getRestorePlanLabel(servicePlan)} Instance
        </Typography>
        <Typography variant="body-lg" c="carbon.7">
          Set up your new instance for restoration. The cloud provider and region of the new instance are the same as
          the backup.
        </Typography>
      </Stack>

      {servicePlan === Commonv1beta1ServicePlan.BYOC ? (
        <>
          <ByocBasicSettingsSection
            cloudProviders={[cloudProvider as V1beta1RegionCloudProvider]}
            regions={regions}
            disabled
            projectOptions={projectOptions}
            onProjectCreated={onProjectCreated}
            withFormLabel={false}
            projectOptional={projectOptional}
            additionalFields={
              <>
                <FormSelect
                  name="resourcePoolId"
                  label="Resource Pool"
                  placeholder="Select a Resource Pool"
                  data={resourcePoolOptions}
                  clearable
                  required
                  disabled={isResourcePoolsLoading || isResourcePoolsError}
                  onChange={(value) => {
                    methods.setValue('resourcePoolId', value || undefined, {
                      shouldDirty: true,
                      shouldTouch: true,
                      shouldValidate: true
                    })
                    if (value) {
                      methods.clearErrors('resourcePoolId')
                    }
                  }}
                />
                {isResourcePoolsError && (
                  <Alert color="red" title="Resource pools could not be loaded">
                    Refresh the page or try again later.
                  </Alert>
                )}
                {canManageResourcePools &&
                  !isResourcePoolsError &&
                  !isResourcePoolsLoading &&
                  resourcePoolOptions.length > 0 && (
                    <Typography variant="body-sm" c="carbon.7">
                      Not suitable resource pool? Go to{' '}
                      <Anchor href={createResourcePoolHref} c="peacock.7" fz={12}>
                        Create New Resource Pool
                      </Anchor>
                    </Typography>
                  )}
                <ResourcePoolVcpuLimitFeedback resourcePoolId={resourcePoolId} validation={resourcePoolValidation} />
                {!isResourcePoolsError && !isResourcePoolsLoading && 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 />
          <ByocCapacitySection projectId={effectiveProjectId} />
          <Divider />
          {isDataEncryptionFeatEnabled && (
            <>
              <ByocDualLayerDataEncryptionSection
                cloudProvider={cloudProvider as V1beta1RegionCloudProvider}
                regionId={regionId}
                projectId={effectiveProjectId}
                readOnly
              />
              <Divider />
            </>
          )}
        </>
      ) : (
        <>
          <PremiumBasicSettingsSection
            cloudProviders={[cloudProvider as V1beta1RegionCloudProvider]}
            regions={regions}
            disabled
            projectOptions={projectOptions}
            onProjectCreated={onProjectCreated}
            withFormLabel={false}
            projectOptional={projectOptional}
          />
          <Divider />
          {servicePlan === Commonv1beta1ServicePlan.Essential_V2 ? (
            <EssentialV2RestoreCapacitySection projectId={effectiveProjectId} />
          ) : (
            <>
              {isPremiumReservedPlan(servicePlan) ? (
                <PremiumReservedCapacitySection
                  projectId={effectiveProjectId}
                  defaultReservedCapacityTemplateId={defaultReservedCapacityTemplateId}
                />
              ) : (
                <PremiumCapacitySection projectId={effectiveProjectId} />
              )}
            </>
          )}
          <Divider />
          {isDataEncryptionFeatEnabled && (
            <>
              <PremiumDualLayerDataEncryptionSection
                cloudProvider={cloudProvider as V1beta1RegionCloudProvider}
                regionId={regionId}
                projectId={effectiveProjectId}
                readOnly
              />
              <Divider />
            </>
          )}
          {servicePlan === Commonv1beta1ServicePlan.Essential_V2 ? (
            <EssentialV2HighAvailabilitySection />
          ) : (
            <PremiumHighAvailabilitySection extraDesc={`${planLabel} supports only regional high availability.`} />
          )}
        </>
      )}
    </>
  )
}

const RestorePremiumSummary = ({
  onCancel,
  formId,
  regions,
  restore,
  sourceName,
  sourcePlan,
  submitDisabled,
  isDataEncryptionFeatEnabled,
  projectId,
  resourcePoolName
}: {
  onCancel: () => void
  formId: string
  regions: Commonv1beta1Region[]
  restore: ReturnType<typeof useTidbServiceRestoreTidb>
  sourceName?: string
  sourcePlan: Commonv1beta1ServicePlan
  submitDisabled: boolean
  isDataEncryptionFeatEnabled: boolean
  projectId: string
  resourcePoolName: string
}) => {
  const {
    store: { tenantData }
  } = useStores()
  const methods = useFormContext<RestoreTargetFormData>()
  const { formState } = methods

  const name = methods.watch('name')
  const cloudProvider = methods.watch('cloudProvider')
  const regionId = methods.watch('regionId')
  const minRcu = methods.watch('minRcu')
  const maxRcu = methods.watch('maxRcu')
  const reservedCapacity = methods.watch('purchasedVcpu')
  const highAvailabilityType = methods.watch('highAvailabilityType')
  const restoreMode = methods.watch('restoreMode')
  const backupId = methods.watch('backupId')
  const pointInTime = methods.watch('pointInTime')
  const backup = methods.watch('backup')
  const encrypted = methods.watch('dualLayerDataEncryption.encrypted')
  const keyType = methods.watch('dualLayerDataEncryption.keyType')

  const regionName = regions.find((item) => item.regionId === regionId)?.displayName ?? regionId ?? '-'
  const dataEncryptionKeyLabel =
    keyType === 'customer-managed'
      ? 'Customer-managed Encryption Key (CMEK)'
      : keyType === 'service-managed'
        ? 'Service-managed Encryption Key'
        : undefined
  const dataEncryptionValue = encrypted
    ? `Enabled${dataEncryptionKeyLabel ? ` with ${dataEncryptionKeyLabel}` : ''}`
    : 'Disabled'

  return (
    <RestoreSummaryCard
      description="Your new instance will be:"
      footer={
        <>
          {sourcePlan === Commonv1beta1ServicePlan.BYOC ? (
            <ByocCost />
          ) : sourcePlan === Commonv1beta1ServicePlan.Essential_V2 ? (
            <EssentialV2Cost
              cloudProvider={cloudProvider as V1beta1RegionCloudProvider}
              regionId={regionId}
              minRcu={minRcu ?? ESSENTIAL_V2_RCU_MIN}
              maxRcu={maxRcu ?? ESSENTIAL_V2_RCU_MIN}
            />
          ) : isPremiumReservedPlan(sourcePlan) ? (
            <PremiumReservedPricingCost
              cloudProvider={cloudProvider ?? ''}
              region={regionId ?? ''}
              projectId={projectId}
            />
          ) : (
            <PremiumPricingCost
              cloudProvider={cloudProvider as V1beta1RegionCloudProvider}
              region={regionId}
              minRcu={minRcu ?? 0}
              maxRcu={maxRcu ?? 0}
            />
          )}

          <Stack gap="md">
            <FormErrorMessage message={getErrorMessage(restore.error, true)} />
            <Group align="center" gap="md">
              <Button variant="default" onClick={onCancel}>
                Cancel
              </Button>
              <Button
                type="submit"
                form={formId}
                loading={restore.isLoading}
                disabled={submitDisabled}
                sx={{ flexGrow: 1 }}
              >
                Restore
              </Button>
            </Group>
          </Stack>
        </>
      }
    >
      <RestoreSummarySection title="Select Backup">
        <RestoreSummaryItem label={`${getRestorePlanLabel(sourcePlan)} Instance`} value={sourceName || '-'} />
        <RestoreSummaryItem
          label="Restore Mode"
          value={restoreMode === Nextgenv1beta2RestoreMode.PITR ? 'Point-in-Time Restore' : 'Snapshot Restore'}
        />
        {restoreMode === Nextgenv1beta2RestoreMode.SNAPSHOT && (
          <RestoreSummaryItem
            label="Backup Snapshot"
            value={backup ? getBackupSnapshotOption(backup, tenantData.timezone).label : backupId || '-'}
          />
        )}
        {restoreMode === Nextgenv1beta2RestoreMode.PITR && (
          <RestoreSummaryItem
            label="Restore Time"
            value={
              pointInTime
                ? formatTime(pointInTime, {
                    offset: tenantData.timezone,
                    showSeconds: true,
                    showTimezone: true
                  })
                : '-'
            }
          />
        )}
      </RestoreSummarySection>

      <RestoreSummarySection title={`Restore to a New ${getRestorePlanLabel(sourcePlan)} Instance`}>
        <RestoreSummaryItem label="Name" value={name || '-'} isError={!!formState.errors.name} />
        <RestoreSummaryItem label="Provider" value={cloudProvider ? getCloudProviderLabel(cloudProvider) : '-'} />
        <RestoreSummaryItem label="Region" value={regionName || '-'} />
        {sourcePlan === Commonv1beta1ServicePlan.BYOC && (
          <RestoreSummaryItem label="Resource Pool" value={resourcePoolName} />
        )}
        <RestoreSummaryItem
          label="Capacity"
          value={
            isPremiumReservedPlan(sourcePlan)
              ? reservedCapacity
                ? `${Number(reservedCapacity).toLocaleString()} vCPU`
                : '-'
              : maxRcu
                ? `Maximum RCU = ${Number(maxRcu).toLocaleString()}`
                : '-'
          }
        />
        {isDataEncryptionFeatEnabled && (
          <RestoreSummaryItem label="Dual-layer Data Encryption" value={dataEncryptionValue} />
        )}
        {sourcePlan !== Commonv1beta1ServicePlan.BYOC && (
          <RestoreSummaryItem
            label="High Availability"
            value={highAvailabilityType === V1beta2TidbHighAvailabilityType.REGIONAL ? 'Regional' : 'Zonal'}
          />
        )}
      </RestoreSummarySection>
    </RestoreSummaryCard>
  )
}

export const CreateRestorePremium = () => {
  const location = useLocation<HistoryState>()
  const { state } = location
  const history = useHistory()
  const { id: tidbId } = useParams<{ id: string }>()
  const { orgId } = useOrgProjectClusterIds()
  const formId = useId()
  const tidb = useSharedTiDBContextSafe()
  const sourceTidb = state?.tidb ?? tidb
  const servicePlan = sourceTidb?.servicePlan ?? Commonv1beta1ServicePlan.Premium
  const defaultCloudProvider = state?.tidb?.cloudProvider ?? tidb?.cloudProvider
  const initialDualLayerDataEncryption = getDualLayerDataEncryptionValue(tidb?.dualLayerDataEncryption)
  const virtualProjectId = useVirtualProjectId()
  const { ownerProjects, isOrgOwner, isAnyProjectOwner } = useCreateResourceRoleState()
  const {
    actions: { fetchUserProfileV2 }
  } = useStores()

  const methods = useForm<RestoreTargetFormData>({
    mode: 'onChange',
    defaultValues: {
      projectId: '',
      restoreMode: Nextgenv1beta2RestoreMode.SNAPSHOT,
      backupId: state?.backup?.id,
      backup: state?.backup,
      name: '',
      cloudProvider: defaultCloudProvider,
      regionId: '',
      resourcePoolId: undefined,
      maxRcu: servicePlan === Commonv1beta1ServicePlan.Essential_V2 ? 10000 : 20000,
      highAvailabilityType: V1beta2TidbHighAvailabilityType.REGIONAL,
      dualLayerDataEncryption: initialDualLayerDataEncryption
    }
  })

  const backup = methods.watch('backup')
  const selectedProjectId = methods.watch('projectId')
  const isRecycleBinRestore = !!(state?.backup && state?.tidb)
  const sourceProjectId = tidb?.computed.projectId ?? ''
  const effectiveProjectId = isOrgOwner ? selectedProjectId || virtualProjectId : selectedProjectId
  const defaultReservedCapacityTemplateId = (sourceTidb as { reservedCapacity?: { id?: string } } | undefined)
    ?.reservedCapacity?.id
  const cloudProvider = methods.watch('cloudProvider')!
  const regionId = methods.watch('regionId')
  const resourcePoolId = methods.watch('resourcePoolId')
  const isByocRestore = servicePlan === Commonv1beta1ServicePlan.BYOC
  const { isEnabled: isDataEncryptionFeatEnabled } = useDualLayerDataEncryptionFeatEnabled({
    servicePlan,
    cloudProvider: cloudProvider as V1beta1RegionCloudProvider
  })
  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]
  )
  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

  useEffect(() => {
    if (isRecycleBinRestore || isOrgOwner || !isAnyProjectOwner) {
      return
    }

    const hasValidProjectSelection =
      !!selectedProjectId && eligibleProjects.some((project) => project.id === selectedProjectId)
    if (hasValidProjectSelection) {
      return
    }

    const nextProjectId =
      eligibleProjects.find((project) => project.id === sourceProjectId)?.id || eligibleProjects[0]?.id || ''
    if (!nextProjectId) {
      return
    }

    methods.setValue('projectId', nextProjectId, { shouldValidate: true })
  }, [
    eligibleProjects,
    isAnyProjectOwner,
    isOrgOwner,
    isRecycleBinRestore,
    methods,
    selectedProjectId,
    sourceProjectId
  ])

  useBackupServiceListDeletedTidbs(
    {
      orgId,
      projectId: '',
      pageSize: 10,
      pageToken: '',
      tidbIds: [state?.tidb?.tidbId || ''],
      includeEncryptionInfo: true
    },
    {
      query: {
        refetchOnWindowFocus: false,
        enabled: !!state?.tidb?.tidbId && !!orgId,
        onSuccess(data) {
          const deletedTidbWithEncryption = data.items?.[0]
          if (deletedTidbWithEncryption?.dualLayerDataEncryption) {
            methods.setValue(
              'dualLayerDataEncryption',
              getDualLayerDataEncryptionValue(deletedTidbWithEncryption.dualLayerDataEncryption)
            )
          }
        }
      }
    }
  )

  const regionsQuery = useRegionServiceListRegions(
    {
      servicePlan,
      orgId,
      projectId: effectiveProjectId
    },
    {
      query: {
        refetchOnWindowFocus: false,
        select: (data) => ({
          ...data,
          regions: data.regions?.filter((region) => {
            const isBackupRegion =
              region.cloudProvider === cloudProvider &&
              (backup ? backup.regionId === region.regionId : region.regionId === sourceTidb?.regionId)

            if (!isBackupRegion || servicePlan !== Commonv1beta1ServicePlan.Essential_V2) {
              return isBackupRegion
            }

            return filterEssentialRegionsByServicePlan([region], 'Essential_V2').length > 0
          })
        })
      },
      request: isByocRestore ? SILENT_BYOC_QUERY_REQUEST : undefined
    }
  )
  const regions = useMemo(() => regionsQuery.data?.regions ?? [], [regionsQuery.data])

  const resourcePoolsQuery = useResourcePoolServiceListResourcePools(
    {
      orgId,
      projectId: effectiveProjectId,
      states: ['ACTIVE'],
      cloudProvider: cloudProvider as ResourcePoolServiceListResourcePoolsCloudProvider,
      regionIds: regionId ? [regionId] : undefined,
      pageSize: 100
    },
    {
      query: {
        enabled: isByocRestore && !!orgId && !!effectiveProjectId && !!cloudProvider && !!regionId,
        refetchOnWindowFocus: false,
        retry: 1
      },
      request: SILENT_BYOC_QUERY_REQUEST
    }
  )
  const resourcePoolValidation = useResourcePoolVcpuLimitValidation({
    enabled: isByocRestore,
    orgId,
    projectId: effectiveProjectId,
    resourcePoolId
  })
  const resourcePoolOptions = useMemo(
    () =>
      (resourcePoolsQuery.data?.resourcePools ?? [])
        .map((pool) => {
          const resourcePool = pool as ResourcePoolSummaryWithVcpuLimit
          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
          }
        })
        .filter((option) => option.value),
    [resourcePoolId, resourcePoolValidation.resourcePool, resourcePoolsQuery.data?.resourcePools]
  )
  const selectedResourcePoolSummary = resourcePoolsQuery.data?.resourcePools?.find(
    (pool) => getResourcePoolId(pool) === resourcePoolId
  )
  const resourcePoolName = selectedResourcePoolSummary?.displayName ?? resourcePoolId ?? '-'
  const isResourcePoolUnavailable =
    isByocRestore &&
    (resourcePoolsQuery.isLoading ||
      resourcePoolsQuery.isError ||
      resourcePoolValidation.isLoading ||
      resourcePoolValidation.isError ||
      resourcePoolValidation.isLimitReached ||
      (resourcePoolsQuery.isSuccess && resourcePoolOptions.length === 0) ||
      !resourcePoolId)

  useEffect(() => {
    const nextRegionId = regions[0]?.regionId ?? ''

    if (!nextRegionId) {
      if (regionId) {
        methods.setValue('regionId', '')
      }
      return
    }

    if (!regionId || !regions.some((region) => region.regionId === regionId)) {
      methods.setValue('regionId', nextRegionId)
    }
  }, [methods, regionId, regions])

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

  const restore = useTidbServiceRestoreTidb()

  const onCancel = () => {
    if (state?.backup && state?.tidb) {
      history.push('/tidbs/recycle-bin')
      return
    }

    history.push(`/tidbs/${tidbId}/backups`)
  }

  const onSubmit = methods.handleSubmit(async (data) => {
    const resolvedProjectId = isOrgOwner ? data.projectId || virtualProjectId : data.projectId

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

    if (servicePlan === Commonv1beta1ServicePlan.BYOC && !data.resourcePoolId) {
      methods.setError('resourcePoolId', { type: 'required', message: 'Required' })
      return
    }

    if (
      servicePlan === Commonv1beta1ServicePlan.BYOC &&
      (resourcePoolValidation.isLoading || resourcePoolValidation.isError || resourcePoolValidation.isLimitReached)
    ) {
      return
    }

    await restore.mutateAsync({
      data: {
        restoreMode: data.restoreMode,
        backupId: data.restoreMode === Nextgenv1beta2RestoreMode.SNAPSHOT ? data.backupId : undefined,
        pointInTime: data.restoreMode === Nextgenv1beta2RestoreMode.PITR ? data.pointInTime : undefined,
        sourceTidbId: tidbId,
        tidb: {
          displayName: data.name,
          servicePlan,
          cloudProvider: data.cloudProvider as V1beta1RegionCloudProvider,
          regionId: data.regionId,
          maxRcu: servicePlan === Commonv1beta1ServicePlan.Premium_Reserved ? '0' : String(data.maxRcu),
          reservedCapacityTemplateId:
            servicePlan === Commonv1beta1ServicePlan.Premium_Reserved ? data.reservedCapacityTemplateId : undefined,
          resourcePoolId: servicePlan === Commonv1beta1ServicePlan.BYOC ? data.resourcePoolId : undefined,
          highAvailabilityType:
            servicePlan === Commonv1beta1ServicePlan.BYOC
              ? undefined
              : servicePlan === Commonv1beta1ServicePlan.Essential_V2
                ? V1beta2TidbHighAvailabilityType.ZONAL
                : data.highAvailabilityType,
          labels: {
            'tidb.cloud/project': resolvedProjectId
          }
        }
      },
      params: {
        orgId,
        projectId: resolvedProjectId
      }
    })

    invalidateCapacityLimitsQueries(queryClient, servicePlan, orgId, resolvedProjectId)
    notifier.success('Restoring to a new instance...')
    history.push(`/tidbs${location.search}`)
  })

  const content = (
    <FormProvider {...methods}>
      <RestoreLayout
        title="Restore"
        rightSection={
          <RestorePremiumSummary
            onCancel={onCancel}
            formId={formId}
            regions={regions}
            restore={restore}
            sourceName={sourceTidb?.displayName}
            sourcePlan={servicePlan}
            submitDisabled={
              isQuotaInsufficient || isResourcePoolUnavailable || restore.isLoading || methods.formState.isSubmitting
            }
            isDataEncryptionFeatEnabled={isDataEncryptionFeatEnabled}
            projectId={effectiveProjectId}
            resourcePoolName={resourcePoolName}
          />
        }
      >
        <Paper component="form" id={formId} onSubmit={onSubmit} withBorder shadow="none">
          <RestoreSelectionSection state={state} servicePlan={servicePlan} />
          <Divider />
          <DestinationConfigSection
            servicePlan={servicePlan}
            regions={regions}
            projectOptions={projectOptions}
            effectiveProjectId={effectiveProjectId}
            projectOptional={isOrgOwner}
            onProjectCreated={fetchUserProfileV2}
            isDataEncryptionFeatEnabled={isDataEncryptionFeatEnabled}
            defaultReservedCapacityTemplateId={defaultReservedCapacityTemplateId}
            resourcePoolOptions={resourcePoolOptions}
            resourcePoolValidation={resourcePoolValidation}
            isResourcePoolsLoading={resourcePoolsQuery.isLoading}
            isResourcePoolsError={resourcePoolsQuery.isError}
          />
        </Paper>
      </RestoreLayout>
    </FormProvider>
  )

  if (isRecycleBinRestore) {
    return <PageAccessGuard id="TidbxBackupRestoreAction">{content}</PageAccessGuard>
  }

  return (
    <PageAccessGuard id="TidbxRestoreCreate" scopeProps={{ tidbId }}>
      {content}
    </PageAccessGuard>
  )
}

export default CreateRestorePremium
