<!--
  页面名称：Settings.vue
  页面描述：系统配置页面（被测系统配置 + 钉钉对接配置）
  路径：/system/settings

  @author czj
  @date 2026-08-13
  @last-modified 2026-08-19
-->
<template>
  <div class="settings-page">
    <!-- 被测系统配置 -->
    <el-card shadow="never" style="margin-bottom: 20px">
      <template #header>
        <div class="card-header">
          <span>被测系统配置</span>
          <el-tag v-if="sutSource" :type="sutSource === 'db' ? 'success' : 'info'" size="small">
            {{ sutSource === 'db' ? '数据库已保存' : '环境变量默认' }}
          </el-tag>
        </div>
      </template>

      <el-form
        ref="sutFormRef"
        :model="sutForm"
        :rules="sutRules"
        label-width="140px"
        label-position="right"
        style="max-width: 600px"
      >
        <el-form-item label="被测系统URL" prop="url">
          <el-input
            v-model="sutForm.url"
            placeholder="请输入被测系统访问 URL，如 https://192.168.5.44"
            clearable
          />
        </el-form-item>

        <el-form-item label="登录接口路径" prop="loginPath">
          <el-input
            v-model="sutForm.loginPath"
            placeholder="/platform/api/auth/login"
            clearable
          />
        </el-form-item>

        <el-form-item label="验证码接口路径" prop="captchaPath">
          <el-input
            v-model="sutForm.captchaPath"
            placeholder="/platform/api/code"
            clearable
          />
        </el-form-item>

        <el-alert
          title="保存后，UI 自动化与性能测试执行即使用该地址和认证路径；服务重启后依然生效。"
          type="info"
          :closable="false"
          show-icon
          style="margin-bottom: 16px"
        />

        <el-form-item>
          <el-button type="primary" :loading="sutSaving" @click="handleSutSave">
            {{ sutSaving ? '保存中...' : '保存配置' }}
          </el-button>
          <el-button @click="handleSutReset">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <!-- 钉钉对接配置 -->
    <el-card shadow="never">
      <template #header>
        <div class="card-header">
          <span>钉钉对接配置</span>
        </div>
      </template>

      <el-form
        ref="formRef"
        :model="form"
        :rules="rules"
        label-width="140px"
        label-position="right"
        style="max-width: 600px"
      >
        <el-form-item label="AppKey" prop="app_key">
          <el-input
            v-model="form.app_key"
            type="password"
            show-password
            placeholder="请输入钉钉应用 AppKey"
            clearable
          />
        </el-form-item>

        <el-form-item label="AppSecret" prop="app_secret">
          <el-input
            v-model="form.app_secret"
            type="password"
            show-password
            placeholder="请输入钉钉应用 AppSecret"
            clearable
          />
        </el-form-item>

        <el-form-item label="AgentId" prop="agent_id">
          <el-input-number
            v-model="form.agent_id"
            :min="0"
            :max="999999999"
            :step="1"
            style="width: 100%"
          />
        </el-form-item>

        <el-form-item>
          <el-button type="primary" :loading="saving" @click="handleSave">
            {{ saving ? '保存中...' : '保存配置' }}
          </el-button>
          <el-button @click="handleReset">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>
  </div>
</template>

<script setup lang="ts">
/**
 * 系统配置页面
 *
 * 功能：
 * 1. 被测系统配置：填写被测系统访问 URL、登录接口路径、验证码接口路径，保存后 UI 自动化与性能测试执行即使用该地址和认证路径（重启持久化）
 * 2. 钉钉对接配置：钉钉应用凭据持久化
 */

import { reactive, ref, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { systemApi } from '@/api/system'

// ==================== 被测系统配置 ====================

const sutFormRef = ref()
const sutSaving = ref(false)
const sutSource = ref('')

const sutForm = reactive({
  url: '',
  loginPath: '',
  captchaPath: '',
})

/** 校验被测系统 URL：http/https + 合法主机（IP 段 0-255 / 合法域名）+ 合法端口 */
function validateSutUrl(_rule: any, value: string, callback: (err?: Error) => void) {
  const url = (value || '').trim()
  if (!url) {
    callback(new Error('请输入被测系统 URL'))
    return
  }
  if (!/^https?:\/\//.test(url)) {
    callback(new Error('URL 需以 http:// 或 https:// 开头'))
    return
  }
  try {
    const parsed = new URL(url)
    const host = parsed.hostname
    if (!host) {
      callback(new Error('URL 缺少主机名'))
      return
    }
    if (parsed.port && !(Number(parsed.port) >= 1 && Number(parsed.port) <= 65535)) {
      callback(new Error('URL 端口必须在 1-65535 之间'))
      return
    }
    // 纯数字点分形式必须是合法 IPv4（每段 0-255）
    if (/^[\d.]+$/.test(host)) {
      const ok = host.split('.').every((seg) => seg !== '' && Number(seg) >= 0 && Number(seg) <= 255)
      if (!ok) {
        callback(new Error('URL 主机无效（IP 地址每段须为 0-255）'))
        return
      }
    }
  } catch {
    callback(new Error('URL 格式无效'))
    return
  }
  callback()
}

const sutRules = {
  url: [
    { required: true, validator: validateSutUrl, trigger: 'blur' },
  ],
}

/** 原始快照，用于重置 */
let sutSnapshot = ''

async function loadSutConfig() {
  try {
    const res = await systemApi.getSutConfig()
    sutForm.url = res.url || ''
    sutForm.loginPath = res.login_path || ''
    sutForm.captchaPath = res.captcha_path || ''
    sutSource.value = res.source || ''
    sutSnapshot = JSON.stringify({ ...sutForm })
  } catch (err: any) {
    ElMessage.error('加载被测系统配置失败：' + (err?.message || '未知错误'))
  }
}

async function handleSutSave() {
  const valid = await sutFormRef.value?.validate().catch(() => false)
  if (!valid) return

  sutSaving.value = true
  try {
    await systemApi.updateSutConfig({
      url: sutForm.url.trim(),
      login_path: sutForm.loginPath.trim(),
      captcha_path: sutForm.captchaPath.trim(),
    })
    ElMessage.success('被测系统配置已保存')
    sutSnapshot = JSON.stringify({ ...sutForm })
    sutSource.value = 'db'
  } catch (err: any) {
    ElMessage.error('保存被测系统配置失败：' + (err?.message || '未知错误'))
  } finally {
    sutSaving.value = false
  }
}

function handleSutReset() {
  const snapshot = JSON.parse(sutSnapshot)
  Object.assign(sutForm, snapshot)
  sutFormRef.value?.clearValidate()
}

// ==================== 钉钉对接配置 ====================

interface DingTalkConfigForm {
  app_key: string
  app_secret: string
  agent_id: number
}

const formRef = ref()
const saving = ref(false)

const form = reactive<DingTalkConfigForm>({
  app_key: '',
  app_secret: '',
  agent_id: 0,
})

/** 原始数据快照，用于重置 */
let originalSnapshot = ''

const rules = {
  app_key: [{ required: true, message: '请输入钉钉 AppKey', trigger: 'blur' }],
  app_secret: [{ required: true, message: '请输入钉钉 AppSecret', trigger: 'blur' }],
  agent_id: [{ required: true, message: '请输入钉钉 AgentId', trigger: 'blur' }],
}

/** 加载钉钉配置 */
async function loadConfig() {
  try {
    const res = await systemApi.getDingTalkConfig()
    Object.assign(form, {
      app_key: res.app_key,
      app_secret: res.app_secret,
      agent_id: res.agent_id,
    })
    originalSnapshot = JSON.stringify({ ...form })
  } catch (err: any) {
    ElMessage.error('加载钉钉配置失败：' + (err?.message || '未知错误'))
  }
}

/** 保存钉钉配置 */
async function handleSave() {
  const valid = await formRef.value?.validate().catch(() => false)
  if (!valid) return

  saving.value = true
  try {
    await systemApi.updateDingTalkConfig({
      app_key: form.app_key,
      app_secret: form.app_secret,
      agent_id: form.agent_id,
    })
    ElMessage.success('钉钉配置已保存')
    originalSnapshot = JSON.stringify({ ...form })
  } catch (err: any) {
    ElMessage.error('保存钉钉配置失败：' + (err?.message || '未知错误'))
  } finally {
    saving.value = false
  }
}

/** 重置表单到加载时的值 */
function handleReset() {
  const snapshot = JSON.parse(originalSnapshot)
  Object.assign(form, snapshot)
  formRef.value?.clearValidate()
}

// ==================== 生命周期 ====================

onMounted(() => {
  loadConfig()
  loadSutConfig()
})
</script>

<style scoped>
.settings-page {
  max-width: 800px;
}

.card-header {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 16px;
  font-weight: 600;
}
</style>
