<template>
  <a-modal
      v-model:visible="visible"
      title="数据库连接配置"
      width="600px"
      :body-style="{ padding: '16px 20px' }"
      @cancel="handleCancel"
  >
    <!-- 错误提示区域 -->
    <a-alert
        v-if="errorMessage"
        type="error"
        show-icon
        closable
        @close="errorMessage = ''"
        class="error-alert"
    >
      {{ errorMessage }}
    </a-alert>

    <a-form :model="form" :rules="rules" ref="formRef" layout="horizontal" :label-col-props="{ span: 6 }"
            :wrapper-col-props="{ span: 18 }" size="small">
      <a-form-item label="连接名称" field="name">
        <a-input v-model="form.name" placeholder="请输入连接名称" size="small"/>
      </a-form-item>
      <a-form-item label="数据库类型" field="type">
        <a-select v-model="form.type" placeholder="请选择数据库类型" @change="handleTypeChange" size="small">
          <a-option value="mysql">MySQL</a-option>
          <a-option value="redis">Redis</a-option>
          <a-option value="mongo">MongoDB</a-option>
        </a-select>
      </a-form-item>
      <a-form-item label="主机地址" field="host">
        <a-input v-model="form.host" placeholder="请输入主机地址" size="small"/>
      </a-form-item>
      <a-form-item label="端口" field="port">
        <a-input-number v-model="form.port" :min="1" :max="65535" placeholder="请输入端口" style="width: 100%"
                        size="small"/>
      </a-form-item>
      <a-form-item label="用户名" field="username" v-if="form.type !== 'redis'">
        <a-input v-model="form.username" placeholder="请输入用户名" size="small"/>
      </a-form-item>
      <a-form-item label="密码" field="password">
        <div v-if="props.connectionId && !isPasswordChanged" class="password-display">
          <a-input
              value="已保存的密码"
              disabled
              class="password-input"
              size="small"
          />
          <a-button type="text" size="mini" @click="isPasswordChanged = true">
            修改密码
          </a-button>
        </div>
        <a-input-password
            v-else
            v-model="form.password"
            :placeholder="getPasswordPlaceholder()"
            size="small"
        />
      </a-form-item>
      <a-form-item :label="form.type === 'redis' ? '数据库编号' : '数据库名'" field="database">
        <a-input v-model="form.database"
                 :placeholder="form.type === 'redis' ? 'Redis DB 编号 (0-15，默认为0)' : '可选，留空则连接所有数据库'"
                 :max-length="100"
                 size="small"/>
      </a-form-item>

      <!-- 数据库过滤选项（仅 MySQL 和 MongoDB） -->
      <template v-if="form.type === 'mysql' || form.type === 'mongo'">
        <a-form-item label="可见数据库" field="visibleDatabases">
          <div class="database-list-container">
            <!-- 顶部工具栏 -->
            <div class="list-toolbar">
              <a-button
                type="outline"
                size="small"
                @click="loadAllDatabases"
                :loading="loadingDatabases"
                :disabled="!canLoadDatabases"
              >
                <template #icon>
                  <icon-refresh />
                </template>
                {{ allDatabases.length > 0 ? '重新加载' : '加载数据库列表' }}
              </a-button>

              <template v-if="allDatabases.length > 0">
                <div class="toolbar-stats">
                  已选 {{ selectedDatabases.length }} / {{ allDatabases.length }}
                </div>
                <a-button size="small" @click="handleSelectAll(true)">全选</a-button>
                <a-button size="small" @click="handleInvertSelection">反选</a-button>
                <a-button size="small" @click="handleSelectAll(false)">清空</a-button>
              </template>
            </div>

            <!-- 空状态 -->
            <div v-if="!loadingDatabases && allDatabases.length === 0" class="list-empty">
              <icon-storage />
              <span>点击上方按钮加载数据库列表</span>
            </div>

            <!-- 数据库列表（复选框） -->
            <div v-else class="database-checkbox-list">
              <div
                v-for="db in allDatabases"
                :key="db"
                class="database-checkbox-item"
              >
                <a-checkbox
                  :model-value="selectedDatabases.includes(db)"
                  :disabled="loadingDatabases"
                  @change="(checked: boolean) => toggleDatabase(db, checked)"
                >
                  {{ db }}
                </a-checkbox>
              </div>
            </div>

            <!-- 提示信息 -->
            <div v-if="allDatabases.length > 0" class="list-tip">
              <icon-info-circle />
              未选择任何数据库时，将展示所有数据库
            </div>
          </div>
        </a-form-item>
      </template>
      
      <!-- MongoDB 专用选项 -->
      <template v-if="form.type === 'mongo'">
        <a-form-item label="认证数据库" field="options.authSource">
          <a-input v-model="optionsForm.authSource" placeholder="留空则使用 admin" size="small"/>
          <template #extra>
            <span class="form-item-extra">MongoDB 用户所在的数据库，通常为 admin（可选）</span>
          </template>
        </a-form-item>
      </template>
    </a-form>
    <template #footer>
      <a-space size="small">
        <a-button @click="handleTest" :loading="testing" size="small">测试连接</a-button>
        <a-button @click="handleCancel" size="small">取消</a-button>
        <a-button type="primary" @click="handleSubmit" :loading="saving" size="small">保存</a-button>
      </a-space>
    </template>
  </a-modal>
</template>

<script setup lang="ts">
import {reactive, ref, watch, computed, nextTick} from 'vue'
import {Message} from '@arco-design/web-vue'
import {
  IconCheckCircle,
  IconClose,
  IconInfoCircle,
  IconRefresh,
  IconStorage
} from '@arco-design/web-vue/es/icon'
import {
  ListDbConnections,
  SaveDbConnection
} from '../../../wailsjs/wailsjs/go/main/App'
import { getConnectionFailedTip, getLoadFailedTip } from '@/utils/database-error'
import { useVisibleDatabases } from '@/composables/useVisibleDatabases'

// 使用 defineModel 简化 v-model:visible 双向绑定（Vue 3.5+）
const visible = defineModel('visible', { type: Boolean, default: false })

// 使用 TypeScript 泛型语法（Vue 3.5+）
const props = defineProps<{
  connectionId?: number | null
}>()

const emit = defineEmits<{
  success: []
}>()

const formRef = ref<any>(null)
const saving = ref(false)
const testing = ref(false)
const errorMessage = ref('')
// 是否修改密码（编辑模式下）
const isPasswordChanged = ref(false)

// 数据库过滤相关
const { parse: parseVisibleDatabases, filter: filterVisibleDatabases } = useVisibleDatabases()
const loadingDatabases = ref(false)
const allDatabases = ref<string[]>([])
const selectedDatabases = ref<string[]>([])

// 是否可以加载数据库列表
const canLoadDatabases = computed(() =>
  !!(form.host && form.port && form.username && (form.password || props.connectionId))
)

const form = reactive({
  name: '',
  type: 'mysql',
  host: '127.0.0.1',
  port: 3306,
  username: '',
  password: '',
  database: '',
  options: '',
  visibleDatabases: ''
})

// 选项表单（用于表单输入）
const optionsForm = reactive({
  authSource: ''
})

// 将 options JSON 字符串解析为 optionsForm
const parseOptionsToForm = (optionsStr: string) => {
  if (!optionsStr || optionsStr.trim() === '') {
    optionsForm.authSource = ''
    return
  }
  
  try {
    const opts = JSON.parse(optionsStr)
    optionsForm.authSource = opts.authSource || ''
    // 认证机制使用自动检测，不需要从选项读取
  } catch (error) {
    console.warn('解析 Options JSON 失败:', error)
    // 解析失败时，清空表单选项
    optionsForm.authSource = ''
  }
}

// 将 optionsForm 和 form.options 合并为 JSON 字符串
const mergeOptionsToJson = (): string => {
  let customOptions: any = {}
  
  // 先解析已有的 JSON（可能包含其他自定义选项）
  if (form.options && form.options.trim() !== '') {
    try {
      customOptions = JSON.parse(form.options)
    } catch (error) {
      console.warn('解析自定义 Options JSON 失败:', error)
    }
  }
  
  // 根据数据库类型合并表单选项（仅 MongoDB）
  if (form.type === 'mongo') {
    // 只有认证数据库不为空时才添加
    if (optionsForm.authSource && optionsForm.authSource.trim() !== '') {
      customOptions.authSource = optionsForm.authSource.trim()
    }
    // 认证机制使用自动检测，不需要添加到选项
  }
  
  // 如果没有任何选项，返回空字符串
  if (Object.keys(customOptions).length === 0) {
    return ''
  }
  
  return JSON.stringify(customOptions)
}

// 表单验证规则
const rules = {
  name: [
    {required: true, message: '请输入连接名称'},
    {maxLength: 100, message: '连接名称长度不能超过100个字符'}
  ],
  type: [{required: true, message: '请选择数据库类型'}],
  host: [
    {required: true, message: '请输入主机地址'},
    {maxLength: 255, message: '主机地址长度不能超过255个字符'}
  ],
  port: [
    {required: true, message: '请输入端口'},
    {
      validator: (value, callback) => {
        if (!value || value < 1 || value > 65535) {
          callback('端口号必须在1-65535之间')
        } else {
          callback()
        }
      }
    }
  ],
  database: [
    {
      validator: (value, callback) => {
        // MySQL 类型时数据库名为可选（允许为空）
        // MongoDB 和 Redis 也为可选
        callback()
      }
    }
  ]
}

// 获取密码输入框的占位符
const getPasswordPlaceholder = () => {
  if (props.connectionId) return '请输入新密码'
  const placeholders = { redis: '可选，留空则无密码连接', mongo: '可选，留空则无认证连接' }
  return placeholders[form.type] || '请输入密码'
}

// 监听类型变化，设置默认端口、主机和用户名
const handleTypeChange = (type) => {
  // 如果主机为空，设置默认值
  if (!form.host || form.host.trim() === '') {
    form.host = '127.0.0.1'
  }

  // 根据类型设置默认端口和用户名
  switch (type) {
    case 'mysql':
      form.port = 3306
      if (!form.username) {
        form.username = 'root'
      }
      // 清空 MongoDB 专用选项
      optionsForm.authSource = ''
      form.options = ''
      break
    case 'redis':
      form.port = 6379
      form.username = '' // Redis 不需要用户名
      if (!form.database) {
        form.database = '0' // Redis 默认 DB 0
      }
      // 清空其他数据库的选项
      optionsForm.authSource = ''
      form.options = ''
      break
    case 'mongo':
    case 'mongodb':
      form.port = 27017
      if (!form.username) {
        form.username = 'admin' // MongoDB 常用默认用户名
      }
      break
  }
  
  // 类型变化时，同步更新 options JSON
  form.options = mergeOptionsToJson()
}

// 加载连接详情
const loadConnection = async () => {
  if (!props.connectionId) {
    resetForm()
    // 新建模式：不自动加载，等用户手动点击
    return
  }

  isLoading.value = true
  try {
    if (!(window as any).go?.main?.App?.ListDbConnections) {
      return
    }

    const connections = await (window as any).go.main.App.ListDbConnections()
    const conn = connections.find(c => c.id === props.connectionId)
    if (conn) {
      form.name = conn.name
      form.type = conn.type
      form.host = conn.host || '127.0.0.1'
      form.port = conn.port || (conn.type === 'mysql' ? 3306 : conn.type === 'redis' ? 6379 : 27017)
      form.username = conn.username || ''
      form.database = conn.database || ''
      // 先解析 options 到表单
      parseOptionsToForm(conn.options || '')
      // 然后设置 form.options（这样不会触发 watch）
      form.options = conn.options || ''
      // 设置可见数据库
      form.visibleDatabases = conn.visible_databases || ''
      // 编辑模式下，默认不修改密码
      form.password = ''
      isPasswordChanged.value = false

      // 恢复数据库选择
      selectedDatabases.value = parseVisibleDatabases(conn.visible_databases || null)

      // 编辑模式：自动加载数据库列表
      nextTick(() => {
        loadAllDatabases()
      })
    }
  } catch (error) {
    console.error('加载连接详情失败:', error)
  } finally {
    isLoading.value = false
  }
}

// 获取要使用的密码（编辑模式下未修改密码时为空）
const getPasswordToUse = () =>
  (props.connectionId && !isPasswordChanged.value) ? '' : (form.password || '')

// 表单验证（返回 true 表示验证通过）
const validateForm = async () => {
  if (!formRef.value) {
    console.error('formRef 未初始化')
    return false
  }
  errorMessage.value = ''
  try {
    await formRef.value.validate()
    return true
  } catch (error) {
    const errorMsg = error?.fields?.[Object.keys(error.fields)[0]]?.[0]?.message || '请检查表单填写是否正确'
    errorMessage.value = errorMsg
    Message.warning(errorMsg)
    return false
  }
}

// 重置表单
const resetForm = () => {
  form.name = ''
  form.type = 'mysql'
  form.host = '127.0.0.1'
  form.port = 3306
  form.username = 'root' // MySQL 默认用户名
  form.password = ''
  form.database = ''
  form.options = ''
  form.visibleDatabases = ''
  optionsForm.authSource = ''
  isPasswordChanged.value = false
  loadingDatabases.value = false
  allDatabases.value = []
  selectedDatabases.value = []
}

// 测试连接（不保存数据）
const handleTest = async () => {
  if (!(await validateForm())) return

  // 检查 Go 后端是否可用
  if (!(window as any).go?.main?.App) {
    const msg = 'Go 后端未就绪，请确保应用已启动'
    errorMessage.value = msg
    Message.error(msg)
    return
  }

  testing.value = true
  try {
    await (window as any).go.main.App.TestDbConnectionWithParams({
      id: props.connectionId || 0,
      type: form.type,
      host: form.host,
      port: form.port,
      username: form.username || '',
      password: getPasswordToUse(),
      database: form.database || '',
      options: mergeOptionsToJson()
    })
    Message.success('连接测试成功')
    errorMessage.value = ''
  } catch (error) {
    const friendlyMsg = getConnectionFailedTip(error, form.type)
    errorMessage.value = friendlyMsg
    Message.error(friendlyMsg)
  } finally {
    testing.value = false
  }
}

// 提交表单
const handleSubmit = async () => {
  if (!(await validateForm())) return

  // 检查 Go 后端是否可用
  if (!(window as any).go?.main?.App) {
    const msg = 'Go 后端未就绪，请确保应用已启动'
    errorMessage.value = msg
    Message.error(msg)
    return
  }

  saving.value = true
  try {
    await (window as any).go.main.App.SaveDbConnection({
      id: props.connectionId || 0,
      name: form.name,
      type: form.type,
      host: form.host,
      port: form.port,
      username: form.username || '',
      password: getPasswordToUse(),
      database: form.database || '',
      options: mergeOptionsToJson(),
      visible_databases: form.visibleDatabases || ''
    })
    Message.success(props.connectionId ? '更新成功' : '保存成功')
    errorMessage.value = ''
    emit('success')
    visible.value = false
  } catch (error) {
    const errorMsg = error?.message || error?.toString() || '未知错误'
    errorMessage.value = '保存失败: ' + errorMsg
    Message.error('保存失败: ' + errorMsg)
  } finally {
    saving.value = false
  }
}

// 取消
const handleCancel = () => {
  errorMessage.value = ''
  visible.value = false
  resetForm()
}

// 是否正在加载连接（用于避免加载时触发 watch）
const isLoading = ref(false)

// 监听 optionsForm 变化，自动同步到 form.options（仅 MongoDB）
watch(
  () => [optionsForm.authSource, form.type],
  () => {
    // 如果正在加载，不触发更新
    if (isLoading.value) {
      return
    }
    // 仅 MongoDB 需要同步选项
    if (visible.value && form.type === 'mongo') {
      form.options = mergeOptionsToJson()
    }
  },
  { deep: true }
)

// 加载全部数据库列表
const loadAllDatabases = async () => {
  if (!canLoadDatabases.value) {
    Message.warning('请先填写连接信息')
    return
  }

  loadingDatabases.value = true
  try {
    const databases = await (window as any).go.main.App.LoadAllDatabases({
      id: props.connectionId || 0,
      type: form.type,
      host: form.host,
      port: form.port,
      username: form.username || '',
      password: getPasswordToUse(),
      database: form.database || '',
      options: mergeOptionsToJson()
    })

    allDatabases.value = databases || []

    // 从已保存的 visibleDatabases 中恢复选择（使用 composable）
    selectedDatabases.value = filterVisibleDatabases(databases, form.visibleDatabases || null)

    Message.success(`成功加载 ${databases.length} 个数据库`)
  } catch (error) {
    Message.error(getLoadFailedTip(error, 'databases'))
  } finally {
    loadingDatabases.value = false
  }
}

// 切换单个数据库选择
const toggleDatabase = (dbName: string, checked: boolean) => {
  const list = selectedDatabases.value
  if (checked && !list.includes(dbName)) {
    list.push(dbName)
  } else if (!checked) {
    selectedDatabases.value = list.filter(db => db !== dbName)
  }
}

// 全选/全不选
const handleSelectAll = (selectAll: boolean) => {
  if (selectAll) {
    selectedDatabases.value = [...allDatabases.value]
  } else {
    selectedDatabases.value = []
  }
}

// 反选
const handleInvertSelection = () => {
  const selectedSet = new Set(selectedDatabases.value)
  selectedDatabases.value = allDatabases.value.filter(db => !selectedSet.has(db))
}

// 监听数据库选择变化，同步到表单
watch(selectedDatabases, (newVal) => {
  if (newVal.length === 0) {
    form.visibleDatabases = ''
  } else {
    form.visibleDatabases = JSON.stringify(newVal)
  }
}, { deep: true })

// 监听 visible 变化
watch(visible, (val) => {
  if (val) {
    errorMessage.value = ''
    loadConnection()
  } else {
    errorMessage.value = ''
    resetForm()
  }
})
</script>

<style scoped>
.error-alert {
  margin-bottom: 12px;
}

.password-display {
  display: flex;
  align-items: center;
  gap: 8px;
}

.password-input {
  flex: 1;
}

.options-item {
  margin-bottom: 8px;
}

.form-item-extra {
  font-size: 12px;
  color: var(--color-text-3);
  margin-top: 4px;
  display: block;
}

.database-list-container {
  width: 100%;
}

/* 顶部工具栏 */
.list-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}

.toolbar-stats {
  font-size: 13px;
  color: var(--color-text-2);
  margin: 0 8px;
}

/* 空状态 */
.list-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 40px 20px;
  color: var(--color-text-3);
  font-size: 13px;
}

.list-empty svg {
  font-size: 32px;
}

/* 复选框列表 */
.database-checkbox-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 8px;
  max-height: 240px;
  overflow-y: auto;
  padding: 12px;
  background: var(--color-fill-2);
  border: 1px solid var(--color-border-2);
  border-radius: 6px;
}

.database-checkbox-item {
  display: flex;
  align-items: center;
}

.database-checkbox-item :deep(.arco-checkbox) {
  width: 100%;
  font-size: 13px;
}

/* 底部提示 */
.list-tip {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
  padding: 8px 12px;
  background: var(--color-fill-1);
  border-radius: 4px;
  font-size: 12px;
  color: var(--color-text-3);
}

.list-tip svg {
  color: var(--color-text-3);
  font-size: 14px;
}
</style>

