import { Box, Button, Card, Divider, Flex, Typography } from '@tidbcloud/uikit'
import { Form } from '@tidbcloud/uikit/biz'
import { observer } from 'mobx-react'
import { useMemo, useState } from 'react'
import { useForm } from 'react-hook-form'
import { useQueryClient } from 'react-query'

import { SharedTiDB } from 'dbaas/screens/NextGen/shared/model/shared-tidb-state'
import {
  getDatabaseAuditLogServiceGetAuditLogSettingQueryKey,
  useDatabaseAuditLogServiceUpdateAuditLogSetting,
  useRegionServiceListRegions
} from 'dbaas/services/api-clients/v2025/tidb-management/v1beta2'
import {
  AuditLogSettingStorageSetting,
  Nextgenv1beta2AuditLogSetting,
  V1beta2CloudProviderInfo,
  V1beta1RegionCloudProvider
} from 'dbaas/services/api-clients/v2025/tidb-management/v1beta2/interface'
import { getErrorMessage } from 'dbaas/services/errorCodes'
import useStores from 'dbaas/stores/useStores'

import { CONFIG_STEP } from '../shared'

import FormContent from './FormContent'
import { normalizeLogFormat } from './helper'
import { IAMPolicy } from './IAMPolicy'
import { LogSettingsModal } from './LogSettings'

interface AuditLogEnableModalProps {
  opened: boolean
  tidb: SharedTiDB
  config?: Nextgenv1beta2AuditLogSetting
  cloudProviderInfo?: V1beta2CloudProviderInfo
  orgId: string
  onClose: () => void
}

const StoreConfig = observer(
  ({ tidb, orgId, onClose, config: initialConfig, cloudProviderInfo }: AuditLogEnableModalProps) => {
    const [configStep, setConfigStep] = useState<CONFIG_STEP>(CONFIG_STEP.SetStorage)

    const [config, setConfig] = useState<Nextgenv1beta2AuditLogSetting>({
      ...initialConfig,
      format: normalizeLogFormat(initialConfig?.format),
      storageSetting: initialConfig?.storageSetting ?? {
        bucketUri: '',
        bucketRegionId: '',
        cloudRoleIdentity: ''
      }
    })

    const {
      store: { lastVisitLocation }
    } = useStores()

    const form = useForm<AuditLogSettingStorageSetting>({
      mode: 'onChange',
      defaultValues: config.storageSetting
    })

    const {
      mutateAsync: updateAuditLogSetting,
      isLoading: isTestLoading,
      error: testConnectionError
    } = useDatabaseAuditLogServiceUpdateAuditLogSetting()

    const { watch, formState } = form
    const bucketUri = watch('bucketUri')
    const cloudRoleIdentity = watch('cloudRoleIdentity')
    const bucketRegionId = watch('bucketRegionId')

    const { data: regionData } = useRegionServiceListRegions(
      {
        orgId: orgId,
        projectId: lastVisitLocation.projectId,
        cloudProvider: tidb.cloudProvider,
        servicePlan: tidb.servicePlan,
        pageSize: 100
      },
      {
        query: {
          enabled: !!tidb.cloudProvider
        }
      }
    )

    const { isDirty: isFormDirty } = formState

    const closeModal = () => {
      form.reset()
      setConfigStep(CONFIG_STEP.Initial)
      onClose()
    }

    const queryClient = useQueryClient()

    const refetchAuditLogSetting = () => {
      return queryClient.invalidateQueries(
        getDatabaseAuditLogServiceGetAuditLogSettingQueryKey(tidb.tidbId ?? '', {
          orgId,
          projectId: lastVisitLocation.projectId
        })
      )
    }

    const testConnectionHandler = async (config: AuditLogSettingStorageSetting) => {
      try {
        await updateAuditLogSetting({
          tidbId: tidb.tidbId ?? '',
          params: {
            orgId,
            projectId: lastVisitLocation.projectId,
            validateOnly: true
          },
          data: {
            storageSetting: {
              ...config
            }
          }
        })

        setConfigStep(CONFIG_STEP.SetSettings)
        setConfig({
          ...initialConfig,
          format: normalizeLogFormat(initialConfig?.format),
          storageSetting: config
        })
      } catch (_e) {}
    }

    const isFormDisabled = useMemo(() => {
      if (tidb.cloudProvider === V1beta1RegionCloudProvider.azure) {
        if (tidb.computed.isBYOC) {
          return !bucketUri
        }
        return !(bucketUri && cloudRoleIdentity)
      }

      return !(bucketUri && cloudRoleIdentity && bucketRegionId)
    }, [bucketUri, bucketRegionId, cloudRoleIdentity, tidb.cloudProvider])

    const isEnableBtnDisabled = useMemo(() => {
      if (configStep === CONFIG_STEP.SetStorage || isFormDisabled || isFormDirty) {
        return true
      }

      return false
    }, [configStep, isFormDisabled, isFormDirty])

    const azureProviderInfo = cloudProviderInfo

    const subscriptionId = azureProviderInfo?.tidbCloudAccountId ?? '--'
    const principalId = azureProviderInfo?.nodeRole ?? '--'

    return (
      <Form layout="none" form={form} withActions={false} onSubmit={testConnectionHandler} onCancel={closeModal}>
        <Box>
          <Flex align="top" gap={16}>
            <Box sx={{ flex: 1 }}>
              <FormContent
                disabled={isTestLoading}
                cloudProvider={tidb.cloudProvider!}
                isBYOC={tidb.computed.isBYOC}
                regions={
                  regionData?.regions?.map((it) => ({
                    label: it.displayName ?? '',
                    value: it.regionId ?? ''
                  })) ?? []
                }
              />
              {tidb.cloudProvider === V1beta1RegionCloudProvider.azure && (
                <Card mt={16} p="lg" withBorder bg="carbon.2">
                  <Typography variant="title-sm" mb={8}>
                    Azure IAM Role Settings
                  </Typography>
                  <Typography variant="body-sm" c="carbon.7">
                    Retrieve these settings to grant TiDB Cloud access to your Azure account.
                  </Typography>

                  <Box
                    mt={16}
                    sx={{
                      display: 'grid',
                      gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))',
                      gap: 16
                    }}
                  >
                    <Box>
                      <Typography variant="label-lg" c="carbon.8">
                        Subscription ID
                      </Typography>
                      <Typography variant="body-lg" c="carbon.7" mt={4} sx={{ wordBreak: 'break-all' }}>
                        {subscriptionId}
                      </Typography>
                    </Box>

                    <Box>
                      <Typography variant="label-lg" c="carbon.8">
                        Principal ID
                      </Typography>
                      <Typography variant="body-lg" c="carbon.7" mt={4} sx={{ wordBreak: 'break-all' }}>
                        {principalId}
                      </Typography>
                    </Box>
                  </Box>
                </Card>
              )}
            </Box>
            {tidb.cloudProvider !== V1beta1RegionCloudProvider.azure && (
              <IAMPolicy tidbId={tidb.tidbId ?? ''} cloudProvider={tidb.cloudProvider!} />
            )}
          </Flex>
          {testConnectionError && <Form.ErrorMessage mt={8} message={getErrorMessage(testConnectionError) || ''} />}
          <Divider mx="-xl" my={16} />
          <Flex justify="flex-end" align="center" gap={16}>
            <Button variant="default" onClick={closeModal}>
              Cancel
            </Button>
            <Button
              disabled={!isEnableBtnDisabled || isTestLoading || isFormDisabled}
              loading={isTestLoading}
              type="submit"
              data-mp-event="Database Audit Logging Test Connection Button Clicked "
            >
              Test Connection and Next
            </Button>
          </Flex>
        </Box>

        <LogSettingsModal
          opened={configStep === CONFIG_STEP.SetSettings}
          config={config}
          tidbId={tidb.tidbId}
          orgId={orgId}
          isUpdate={false}
          onConfirm={async () => {
            await refetchAuditLogSetting()
            closeModal()
          }}
          onCancel={() => closeModal()}
          onPrevious={() => {
            setConfigStep(CONFIG_STEP.SetStorage)
          }}
        />
      </Form>
    )
  }
)

export default StoreConfig
