<script setup lang="ts">
import { FormInst, FormItemRule, FormRules, ScrollbarInst } from 'naive-ui'
import { nextTick, reactive, readonly, ref, shallowReadonly, useTemplateRef, watch, watchEffect } from 'vue'
import { useI18n } from 'vue-i18n'
import CustomModal from '@/components/custom-modal/custom-modal.vue'
import DatabaseDirectIcon from '@/assets/svgs/database-direct.svg'
import { fetchTestConnectionDataBase } from '@/apis/database'
import { DatabaseFormInterface } from '../type.d'

interface Props {
  btnLoading: boolean
}

defineProps<Props>()

const emit = defineEmits<{
  (e: 'confirm', databaseFormData: DatabaseFormInterface): void
}>()

const { t } = useI18n()

const showModal = defineModel<boolean>('showModal', { required: true })

const databaseFormRef = ref<FormInst | null>(null)
const scrollbarRef = useTemplateRef<ScrollbarInst | null>('scrollbarRef')

let databaseFormData = reactive<DatabaseFormInterface>(databaseFormDataFactory())

const databaseFormRules = shallowReadonly<FormRules>({
  title: [
    {
      key: 'title',
      required: true,
      validator: (_rule: FormItemRule, value: string) => {
        const pattern = /^[\u4e00-\u9fa5a-zA-Z0-9_\-\\.]+$/

        if (!value) {
          return new Error(t('personal_space_module.database_module.please_enter_db_title'))
        } else if (!pattern.test(value)) {
          return new Error(t('personal_space_module.database_module.db_title_rule'))
        }

        return
      },
      trigger: 'blur',
    },
  ],
  dbType: [
    {
      required: true,
      message: t('personal_space_module.database_module.please_select_db_source_type'),
      trigger: 'blur',
    },
  ],
  dbHost: [
    {
      required: true,
      message: t('personal_space_module.database_module.please_enter_db_host'),
      trigger: 'blur',
    },
  ],
  dbPort: [
    {
      required: true,
      message: t('personal_space_module.database_module.please_enter_db_port'),
      trigger: 'blur',
      type: 'number',
    },
  ],
  dbName: [
    { required: true, message: t('personal_space_module.database_module.please_enter_db_name'), trigger: 'blur' },
  ],
  dbUsername: [
    { required: true, message: t('personal_space_module.database_module.please_enter_db_username'), trigger: 'blur' },
  ],
  dbPassword: [
    { required: true, message: t('personal_space_module.database_module.please_enter_db_password'), trigger: 'blur' },
  ],
})

const databaseTypeList = readonly([
  {
    id: 'KJ7rCkq3HNOk',
    icon: DatabaseDirectIcon,
    type: 'Direct',
    name: t('personal_space_module.database_module.direct_database_connection'),
  },
])

const databaseSourceTypeOptions = [
  {
    label: 'MySQL',
    value: 'MySQL',
  },
]

const isConnectDBSuccess = ref(false)
const showConnectStatus = ref(false)
const connectBtnLoading = ref(false)

watch(
  () => [
    databaseFormData.dbType,
    databaseFormData.dbHost,
    databaseFormData.dbPort,
    databaseFormData.dbName,
    databaseFormData.dbUsername,
    databaseFormData.dbPassword,
  ],
  () => {
    showConnectStatus.value = false
    isConnectDBSuccess.value = false
  },
)

watchEffect(() => {
  if (showModal.value) {
    databaseFormData = Object.assign(databaseFormData, databaseFormDataFactory())
    showConnectStatus.value = false
    isConnectDBSuccess.value = false
  }
})

function databaseFormDataFactory(): DatabaseFormInterface {
  return {
    title: '',
    desc: '',
    dbType: 'MYSQL',
    dbHost: '',
    dbPort: 3306,
    dbName: '',
    dbUsername: '',
    dbPassword: '',
  }
}

function handleConnectDatabase() {
  databaseFormRef.value?.validate(
    async (errors) => {
      if (!errors) {
        const { dbType, dbHost, dbPort, dbName, dbUsername, dbPassword } = databaseFormData

        const payload = {
          dbType,
          dbHost,
          dbPort,
          dbName,
          dbUsername,
          dbPassword,
        }

        connectBtnLoading.value = true

        const res = await fetchTestConnectionDataBase<{ status: 'success' | 'fail' }>(payload).finally(() => {
          showConnectStatus.value = true
          connectBtnLoading.value = false
          nextTick(() => {
            scrollbarRef.value?.scrollTo({ top: 9999, behavior: 'smooth' })
          })
        })

        if (res.code === 0) {
          isConnectDBSuccess.value = res.data.status === 'success'
        }
      }
    },
    (rule) => {
      return rule?.key !== 'title'
    },
  )
}

function handleCreateDatabase() {
  databaseFormRef.value?.validate((errors) => {
    if (!errors) {
      if (!isConnectDBSuccess.value) {
        window.$message.warning(t('personal_space_module.database_module.connect_test_must_pass_to_create'))
        return
      }

      emit('confirm', databaseFormData)
    }
  })
}
</script>

<template>
  <CustomModal
    v-model:is-show="showModal"
    :title="t('personal_space_module.database_module.create_database')"
    :width="534"
    :confirm-btn-text="t('common_module.create')"
    :btn-loading="btnLoading"
    :content-style="{ padding: '0 12px 24px' }"
    @confirm="handleCreateDatabase"
  >
    <template #content>
      <n-scrollbar ref="scrollbarRef" style="max-height: 550px" class="px-3">
        <n-form ref="databaseFormRef" :model="databaseFormData" :rules="databaseFormRules">
          <n-form-item :label="t('personal_space_module.database_module.creation_method')">
            <div
              v-for="databaseTypeItem in databaseTypeList"
              :key="databaseTypeItem.id"
              class="flex-center border-theme-color rounded-theme text-theme-color h-[66px] min-w-[110px] cursor-pointer flex-col gap-[2px] border px-2.5"
            >
              <img :src="databaseTypeItem.icon" class="h-6 w-6" />
              <n-ellipsis>
                <span>{{ databaseTypeItem.name }}</span>
              </n-ellipsis>
            </div>
          </n-form-item>
          <n-form-item
            path="title"
            :label="t('personal_space_module.database_module.db_title')"
            :feedback-style="{ fontSize: '13px' }"
          >
            <div class="flex w-full flex-col">
              <n-input
                v-model:value="databaseFormData.title"
                :placeholder="t('personal_space_module.database_module.please_enter_db_title')"
                show-count
                :maxlength="50"
              />
              <span class="text-gray-font-color mt-1 px-2.5 text-[12px]">
                {{ t('personal_space_module.database_module.db_title_rule') }}
              </span>
            </div>
          </n-form-item>

          <n-form-item :label="t('personal_space_module.database_module.db_desc')">
            <n-input
              v-model:value="databaseFormData.desc"
              :placeholder="t('personal_space_module.database_module.please_enter_db_desc')"
              show-count
              :maxlength="100"
              type="textarea"
              :autosize="{ minRows: 3, maxRows: 5 }"
            />
          </n-form-item>

          <h3 class="font-family-medium mb-4 text-[18px]">
            {{ t('personal_space_module.database_module.db_source_info') }}
          </h3>

          <n-form-item
            path="dbType"
            :label="t('personal_space_module.database_module.db_source_type')"
            :feedback-style="{ fontSize: '13px' }"
          >
            <n-select
              v-model:value="databaseFormData.dbType"
              :placeholder="t('personal_space_module.database_module.please_select_db_source_type')"
              :options="databaseSourceTypeOptions"
            />
          </n-form-item>

          <n-form-item
            path="dbHost"
            :label="t('personal_space_module.database_module.db_host')"
            :feedback-style="{ fontSize: '13px' }"
          >
            <div class="flex w-full flex-col">
              <n-input
                v-model:value="databaseFormData.dbHost"
                :placeholder="t('personal_space_module.database_module.please_enter_db_host')"
              />
              <span class="mt-1 px-2.5 text-[13px] text-[#6F77FF]">
                {{ t('personal_space_module.database_module.db_host_rule') }}
              </span>
            </div>
          </n-form-item>

          <n-form-item
            path="dbPort"
            :label="t('personal_space_module.database_module.db_port')"
            :feedback-style="{ fontSize: '13px' }"
          >
            <n-input-number
              v-model:value="databaseFormData.dbPort"
              class="w-full"
              :placeholder="t('personal_space_module.database_module.please_enter_db_port')"
              :show-button="false"
              :max="65535"
              :min="1"
            />
          </n-form-item>

          <n-form-item
            path="dbName"
            :label="t('personal_space_module.database_module.db_name')"
            :feedback-style="{ fontSize: '13px' }"
          >
            <n-input
              v-model:value="databaseFormData.dbName"
              :placeholder="t('personal_space_module.database_module.please_enter_db_name')"
            />
          </n-form-item>

          <n-form-item
            path="dbUsername"
            :label="t('personal_space_module.database_module.db_username')"
            :feedback-style="{ fontSize: '13px' }"
          >
            <n-input
              v-model:value="databaseFormData.dbUsername"
              :placeholder="t('personal_space_module.database_module.please_enter_db_username')"
            />
          </n-form-item>

          <n-form-item
            path="dbPassword"
            :label="t('personal_space_module.database_module.db_password')"
            :feedback-style="{ fontSize: '13px' }"
          >
            <n-input
              v-model:value="databaseFormData.dbPassword"
              type="password"
              show-password-on="click"
              :input-props="{ autocomplete: 'off' }"
              :placeholder="t('personal_space_module.database_module.please_enter_db_password')"
              class="font-sans"
            />
          </n-form-item>
        </n-form>

        <div
          v-show="showConnectStatus"
          class="flex items-center gap-[8px] rounded-[10px] px-3 py-[5px]"
          :class="isConnectDBSuccess ? 'bg-[#ECFFE6]' : 'bg-[#FFE8E6]'"
        >
          <div class="h-[16px] w-[16px]" :class="isConnectDBSuccess ? 'bg-svg-success' : 'bg-svg-error'" />
          <span class="text-[12px] leading-[16px]">
            {{
              isConnectDBSuccess
                ? t('personal_space_module.database_module.connect_test_success')
                : t('personal_space_module.database_module.connect_test_fail')
            }}
          </span>
        </div>

        <div class="flex-center mt-5">
          <n-button
            type="primary"
            color="#6F77FF"
            class="h-[34px]!"
            :bordered="false"
            :focusable="false"
            :loading="connectBtnLoading"
            @click="handleConnectDatabase"
          >
            {{ t('personal_space_module.database_module.connect_test') }}
          </n-button>
        </div>
      </n-scrollbar>
    </template>
  </CustomModal>
</template>

<style lang="scss" scoped>
:deep(.n-form-item-label__text) {
  font-family: 'SourceHanSansCN-Medium';
}
</style>
