<script setup>
import { ref, reactive, onMounted, computed, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Delete, Plus, CopyDocument, Grid, Edit } from '@element-plus/icons-vue'
import api from '@/api'
import { useAuthStore } from '@/stores/auth'

const authStore = useAuthStore()

const loading = ref(false)
const tableData = ref([])
const total = ref(0)
const query = reactive({
  page: 1,
  size: 20,
  tenant_id: '',
  app_code: ''
})

// 租户列表
const tenantList = ref([])
const tenantMap = ref({}) // code -> name 映射

// 应用列表（从应用管理获取）
const appList = ref([])
const appMap = ref({}) // app_code -> app_name 映射
const appRequireJssdk = ref({}) // app_code -> require_jssdk
const appBaseUrl = ref({}) // app_code -> base_url
const appConfigSchema = ref({}) // app_code -> config_schema

// 企微应用列表（按租户）
const wechatAppList = ref([])

// 对话框
const dialogVisible = ref(false)
const dialogTitle = ref('')
const editingId = ref(null)
const formRef = ref(null)
const form = reactive({
  tenant_id: '',
  app_code: '',
  app_name: '',
  wechat_app_id: null,
  custom_configs: []  // 自定义配置 [{key, value, remark}]
})

// 当前选择的应用是否需要 JS-SDK
const currentAppRequireJssdk = computed(() => {
  return appRequireJssdk.value[form.app_code] || false
})

// 当前应用的配置项定义
const currentConfigSchema = computed(() => {
  return appConfigSchema.value[form.app_code] || []
})

// 配置值映射（方便读写）
const configValues = computed(() => {
  const map = {}
  form.custom_configs.forEach(c => {
    map[c.key] = c
  })
  return map
})

// 获取配置值
function getConfigValue(key) {
  return configValues.value[key]?.value || ''
}

// 设置配置值
function setConfigValue(key, value, remark = '') {
  const existing = form.custom_configs.find(c => c.key === key)
  if (existing) {
    existing.value = value
    if (remark) existing.remark = remark
  } else {
    form.custom_configs.push({ key, value, remark })
  }
}

// 获取选项显示名称
function getOptionLabel(schema, optionValue) {
  if (schema.option_labels && schema.option_labels[optionValue]) {
    return schema.option_labels[optionValue]
  }
  return optionValue
}

// 打开长文本编辑弹窗
function openTextEdit(index, schema) {
  textEditData.index = index
  textEditData.label = schema.label || schema.key
  textEditData.value = form.custom_configs[index]?.value || ''
  textEditData.placeholder = schema.placeholder || '请输入内容'
  textEditDialogVisible.value = true
}

// 保存长文本编辑
function saveTextEdit() {
  if (textEditData.index >= 0 && form.custom_configs[textEditData.index]) {
    form.custom_configs[textEditData.index].value = textEditData.value
  }
  textEditDialogVisible.value = false
}

// 获取文本预览（截取前N个字符）
function getTextPreview(text, maxLength = 80) {
  if (!text) return '（未填写）'
  if (text.length <= maxLength) return text
  return text.slice(0, maxLength) + '...'
}

// 判断文本是否为长文本（超过80字符或多行）
function isLongText(text) {
  if (!text) return false
  return text.length > 80 || text.includes('\n')
}

// 验证 app_code 必须是有效的应用
const validateAppCode = (rule, value, callback) => {
  if (!value) {
    callback(new Error('请选择应用'))
  } else if (!appList.value.find(a => a.app_code === value)) {
    callback(new Error('请从列表中选择有效的应用'))
  } else {
    callback()
  }
}

const rules = {
  tenant_id: [{ required: true, message: '请选择租户', trigger: 'change' }],
  app_code: [{ required: true, validator: validateAppCode, trigger: 'change' }]
}

// 监听租户选择变化
watch(() => form.tenant_id, async (newVal) => {
  if (newVal) {
    await fetchWechatApps(newVal)
  } else {
    wechatAppList.value = []
  }
  form.wechat_app_id = null
})

// 监听应用选择变化，初始化配置默认值
watch(() => form.app_code, (newVal) => {
  if (newVal && !editingId.value) {
    // 新建时，根据 schema 初始化默认值
    initConfigDefaults()
  }
})

// 查看 Token 对话框
const tokenDialogVisible = ref(false)
const currentToken = ref('')
const currentAppUrl = ref('')

// 批量添加对话框
const batchDialogVisible = ref(false)
const batchLoading = ref(false)
const batchForm = reactive({
  tenant_id: '',
  selected_apps: []
})

// 长文本编辑弹窗
const textEditDialogVisible = ref(false)
const textEditData = reactive({
  index: -1,
  label: '',
  value: '',
  placeholder: ''
})

// 获取租户尚未订阅的应用列表
const availableAppsForBatch = computed(() => {
  if (!batchForm.tenant_id) return appList.value
  
  // 获取该租户已订阅的应用
  const subscribedApps = new Set(
    tableData.value
      .filter(row => row.tenant_id === batchForm.tenant_id)
      .map(row => row.app_code)
  )
  
  // 返回未订阅的应用
  return appList.value.filter(app => !subscribedApps.has(app.app_code))
})

// 是否全选
const isAllSelected = computed(() => {
  return availableAppsForBatch.value.length > 0 && 
    batchForm.selected_apps.length === availableAppsForBatch.value.length
})

// 是否部分选中
const isIndeterminate = computed(() => {
  return batchForm.selected_apps.length > 0 && 
    batchForm.selected_apps.length < availableAppsForBatch.value.length
})

async function fetchTenants() {
  try {
    const res = await api.get('/api/tenants', { params: { size: 1000 } })
    tenantList.value = res.data.items || []
    // 构建 code -> name 映射
    const map = {}
    tenantList.value.forEach(t => {
      map[t.code] = t.name
    })
    tenantMap.value = map
  } catch (e) {
    console.error('获取租户列表失败:', e)
  }
}

// 获取租户中文名
function getTenantName(code) {
  return tenantMap.value[code] || code
}

// 获取应用中文名
function getAppName(code) {
  return appMap.value[code] || code
}

async function fetchApps() {
  try {
    const res = await api.get('/api/apps', { params: { size: 100 } })
    const apps = res.data.items || []
    appList.value = apps.map(a => ({ app_code: a.app_code, app_name: a.app_name }))
    
    // 构建 app_code -> app_name 映射
    const map = {}
    for (const app of apps) {
      map[app.app_code] = app.app_name
      appRequireJssdk.value[app.app_code] = app.require_jssdk || false
      appBaseUrl.value[app.app_code] = app.base_url || ''
      appConfigSchema.value[app.app_code] = app.config_schema || []
    }
    appMap.value = map
  } catch (e) {
    console.error('获取应用列表失败:', e)
  }
}

// 根据 schema 初始化配置默认值
function initConfigDefaults() {
  const schema = currentConfigSchema.value
  if (!schema.length) return
  
  form.custom_configs = schema.map(s => ({
    key: s.key,
    value: s.default || '',
    remark: ''
  }))
}

async function fetchWechatApps(tenantId) {
  if (!tenantId) {
    wechatAppList.value = []
    return
  }
  try {
    const res = await api.get(`/api/tenant-wechat-apps/by-tenant/${tenantId}`)
    wechatAppList.value = res.data || []
  } catch (e) {
    wechatAppList.value = []
  }
}

async function fetchList() {
  loading.value = true
  try {
    const res = await api.get('/api/tenant-apps', { params: query })
    tableData.value = res.data.items || []
    total.value = res.data.total || 0
  } catch (e) {
    console.error(e)
  } finally {
    loading.value = false
  }
}

function handleSearch() {
  query.page = 1
  fetchList()
}

function handlePageChange(page) {
  query.page = page
  fetchList()
}

function handleCreate() {
  editingId.value = null
  dialogTitle.value = '新建应用订阅'
  Object.assign(form, {
    tenant_id: '',
    app_code: '',
    app_name: '',
    wechat_app_id: null,
    custom_configs: []
  })
  wechatAppList.value = []
  dialogVisible.value = true
}

async function handleEdit(row) {
  editingId.value = row.id
  dialogTitle.value = '编辑应用订阅'
  
  // 先获取 schema
  const schema = appConfigSchema.value[row.app_code] || []
  
  // 合并已有配置和 schema 默认值
  const existingConfigs = row.custom_configs || []
  const existingMap = {}
  existingConfigs.forEach(c => { existingMap[c.key] = c })
  
  // 构建完整的配置列表（包含 schema 中的所有配置项）
  const mergedConfigs = schema.map(s => ({
    key: s.key,
    value: existingMap[s.key]?.value ?? s.default ?? '',
    remark: existingMap[s.key]?.remark ?? ''
  }))
  
  // 添加 schema 中没有但已存在的配置（兼容旧数据）
  existingConfigs.forEach(c => {
    if (!schema.find(s => s.key === c.key)) {
      mergedConfigs.push({ ...c })
    }
  })
  
  Object.assign(form, {
    tenant_id: row.tenant_id,
    app_code: row.app_code,
    app_name: row.app_name || '',
    wechat_app_id: row.wechat_app_id || null,
    custom_configs: mergedConfigs
  })
  await fetchWechatApps(row.tenant_id)
  dialogVisible.value = true
}

// 自定义配置管理（用于没有 schema 定义时的手动添加）
function addCustomConfig() {
  form.custom_configs.push({ key: '', value: '', remark: '' })
}

function removeCustomConfig(index) {
  form.custom_configs.splice(index, 1)
}


async function handleSubmit() {
  await formRef.value.validate()
  
  const data = { ...form }
  
  try {
    if (editingId.value) {
      await api.put(`/api/tenant-apps/${editingId.value}`, data)
      ElMessage.success('更新成功')
    } else {
      const res = await api.post('/api/tenant-apps', data)
      ElMessage.success(`创建成功`)
      // 显示新生成的 token
      showToken(res.data.access_token, form.app_code)
    }
    dialogVisible.value = false
    fetchList()
  } catch (e) {
    // 错误已在拦截器处理
  }
}

async function handleDelete(row) {
  await ElMessageBox.confirm(`确定删除「${row.app_code}」的订阅配置吗？`, '提示', {
    type: 'warning'
  })
  
  try {
    await api.delete(`/api/tenant-apps/${row.id}`)
    ElMessage.success('删除成功')
    fetchList()
  } catch (e) {
    // 错误已在拦截器处理
  }
}

async function handleRegenerateToken(row) {
  await ElMessageBox.confirm('重新生成 Token 将使旧 Token 失效，确定继续？', '提示', {
    type: 'warning'
  })
  
  try {
    const res = await api.post(`/api/tenant-apps/${row.id}/regenerate-token`)
    showToken(res.data.access_token, row.app_code)
    fetchList()
  } catch (e) {
    // 错误已在拦截器处理
  }
}

function showToken(token, appCode) {
  currentToken.value = token
  currentAppUrl.value = appBaseUrl.value[appCode] || ''
  tokenDialogVisible.value = true
}

function handleCopyToken() {
  navigator.clipboard.writeText(currentToken.value).then(() => {
    ElMessage.success('Token 已复制')
  })
}

function handleCopyUrl() {
  const url = `${currentAppUrl.value}?token=${currentToken.value}`
  navigator.clipboard.writeText(url).then(() => {
    ElMessage.success('链接已复制')
  })
}

async function handleViewToken(row) {
  try {
    const res = await api.get(`/api/tenant-apps/${row.id}/token`)
    currentToken.value = res.data.access_token
    currentAppUrl.value = res.data.base_url || ''
    tokenDialogVisible.value = true
  } catch (e) {
    // 错误已在拦截器处理
  }
}

// 快速选择租户标签
function selectTenant(code) {
  if (query.tenant_id === code) {
    query.tenant_id = ''  // 再次点击取消选中
  } else {
    query.tenant_id = code
  }
  handleSearch()
}

// 复制带 token 的链接
async function copyTokenLink(row) {
  try {
    const res = await api.get(`/api/tenant-apps/${row.id}/token`)
    const token = res.data.access_token
    const baseUrl = res.data.base_url || appBaseUrl.value[row.app_code] || ''
    
    if (!baseUrl) {
      ElMessage.warning('该应用未配置访问地址')
      return
    }
    
    const url = `${baseUrl}?token=${token}`
    await navigator.clipboard.writeText(url)
    ElMessage.success('链接已复制')
  } catch (e) {
    ElMessage.error('复制失败')
  }
}

// 打开批量添加对话框
function handleBatchCreate() {
  batchForm.tenant_id = ''
  batchForm.selected_apps = []
  batchDialogVisible.value = true
}

// 监听批量添加租户变化
watch(() => batchForm.tenant_id, () => {
  batchForm.selected_apps = []
})

// 全选/取消全选
function toggleSelectAll(checked) {
  if (checked) {
    batchForm.selected_apps = availableAppsForBatch.value.map(app => app.app_code)
  } else {
    batchForm.selected_apps = []
  }
}

// 批量创建订阅
async function handleBatchSubmit() {
  if (!batchForm.tenant_id) {
    ElMessage.warning('请选择租户')
    return
  }
  if (batchForm.selected_apps.length === 0) {
    ElMessage.warning('请至少选择一个应用')
    return
  }
  
  batchLoading.value = true
  const results = { success: 0, failed: 0 }
  const createdTokens = []
  
  try {
    for (const appCode of batchForm.selected_apps) {
      try {
        const res = await api.post('/api/tenant-apps', {
          tenant_id: batchForm.tenant_id,
          app_code: appCode,
          app_name: '',
          custom_configs: []
        })
        results.success++
        
        // 收集生成的 token 信息
        if (res.data.access_token) {
          createdTokens.push({
            app_code: appCode,
            app_name: appMap.value[appCode] || appCode,
            token: res.data.access_token,
            base_url: appBaseUrl.value[appCode] || ''
          })
        }
      } catch (e) {
        results.failed++
        console.error(`创建 ${appCode} 订阅失败:`, e)
      }
    }
    
    if (results.success > 0) {
      ElMessage.success(`成功创建 ${results.success} 个订阅${results.failed > 0 ? `，${results.failed} 个失败` : ''}`)
      batchDialogVisible.value = false
      fetchList()
      
      // 如果有创建成功的，显示批量 Token 结果
      if (createdTokens.length > 0) {
        showBatchTokens(createdTokens)
      }
    } else {
      ElMessage.error('创建失败，可能应用已被订阅')
    }
  } finally {
    batchLoading.value = false
  }
}

// 批量 Token 显示
const batchTokenDialogVisible = ref(false)
const batchTokenList = ref([])

function showBatchTokens(tokens) {
  batchTokenList.value = tokens
  batchTokenDialogVisible.value = true
}

// 复制单个 Token 链接
function copyBatchTokenLink(item) {
  if (!item.base_url) {
    ElMessage.warning('该应用未配置访问地址')
    return
  }
  const url = `${item.base_url}?token=${item.token}`
  navigator.clipboard.writeText(url).then(() => {
    ElMessage.success(`${item.app_name} 链接已复制`)
  })
}

// 复制所有 Token 链接
function copyAllTokenLinks() {
  const links = batchTokenList.value
    .filter(item => item.base_url)
    .map(item => `${item.app_name}: ${item.base_url}?token=${item.token}`)
    .join('\n\n')
  
  if (!links) {
    ElMessage.warning('没有可复制的链接')
    return
  }
  
  navigator.clipboard.writeText(links).then(() => {
    ElMessage.success('所有链接已复制')
  })
}

onMounted(() => {
  fetchTenants()
  fetchApps()
  fetchList()
})
</script>

<template>
  <div class="page-container">
    <div class="page-header">
      <div class="title">租户应用订阅</div>
      <div class="header-actions">
        <el-button v-if="authStore.isOperator" type="success" @click="handleBatchCreate">
          <el-icon><Grid /></el-icon>
          批量添加
        </el-button>
        <el-button v-if="authStore.isOperator" type="primary" @click="handleCreate">
          <el-icon><Plus /></el-icon>
          新建订阅
        </el-button>
      </div>
    </div>
    
    <div class="page-tip">
      <el-alert type="info" :closable="false">
        为租户订阅应用，生成访问 Token。外部应用可通过 Token 向平台验证身份。
      </el-alert>
    </div>
    
    <!-- 租户快速筛选标签 -->
    <div class="tenant-tags">
      <span class="tag-label">租户筛选：</span>
      <el-tag
        v-for="tenant in tenantList"
        :key="tenant.code"
        :type="query.tenant_id === tenant.code ? '' : 'info'"
        :effect="query.tenant_id === tenant.code ? 'dark' : 'plain'"
        class="tenant-tag"
        @click="selectTenant(tenant.code)"
      >
        {{ tenant.name }}
      </el-tag>
      <el-tag 
        v-if="query.tenant_id" 
        type="danger" 
        effect="plain" 
        class="tenant-tag clear-tag"
        @click="selectTenant('')"
      >
        清除筛选
      </el-tag>
    </div>
    
    <!-- 搜索栏 -->
    <div class="search-bar">
      <el-select v-model="query.app_code" placeholder="选择应用" clearable style="width: 150px">
        <el-option v-for="app in appList" :key="app.app_code" :label="app.app_name" :value="app.app_code" />
      </el-select>
      <el-button type="primary" @click="handleSearch">搜索</el-button>
    </div>
    
    <!-- 表格 -->
    <el-table v-loading="loading" :data="tableData" style="width: 100%">
      <el-table-column prop="id" label="ID" width="60" />
      <el-table-column label="租户" width="120">
        <template #default="{ row }">
          <span class="cell-name">{{ getTenantName(row.tenant_id) }}</span>
        </template>
      </el-table-column>
      <el-table-column label="应用" width="150">
        <template #default="{ row }">
          <span class="cell-name">{{ getAppName(row.app_code) }}</span>
        </template>
      </el-table-column>
      <el-table-column prop="app_name" label="备注" width="120" />
      <el-table-column label="快捷链接" width="100">
        <template #default="{ row }">
          <el-button 
            v-if="row.access_token && appBaseUrl[row.app_code]" 
            type="primary" 
            link 
            size="small" 
            @click="copyTokenLink(row)"
          >
            <el-icon><CopyDocument /></el-icon>
            复制
          </el-button>
          <span v-else style="color: #c0c4cc; font-size: 12px">-</span>
        </template>
      </el-table-column>
      <el-table-column label="企微应用" width="140">
        <template #default="{ row }">
          <template v-if="row.wechat_app">
            <el-tag type="success" size="small">{{ row.wechat_app.name }}</el-tag>
          </template>
          <el-tag v-else type="info" size="small">未关联</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="配置" width="80">
        <template #default="{ row }">
          <el-tag v-if="row.custom_configs && row.custom_configs.length > 0" type="primary" size="small">
            {{ row.custom_configs.length }} 项
          </el-tag>
          <span v-else style="color: #909399; font-size: 12px">-</span>
        </template>
      </el-table-column>
      <el-table-column label="状态" width="70">
        <template #default="{ row }">
          <el-tag :type="row.status === 1 ? 'success' : 'info'" size="small">
            {{ row.status === 1 ? '启用' : '禁用' }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="240" fixed="right">
        <template #default="{ row }">
          <el-button v-if="authStore.isOperator" type="primary" link size="small" @click="handleEdit(row)">编辑</el-button>
          <el-button v-if="authStore.isOperator" type="success" link size="small" @click="handleViewToken(row)">Token</el-button>
          <el-button v-if="authStore.isOperator" type="warning" link size="small" @click="handleRegenerateToken(row)">重置</el-button>
          <el-button v-if="authStore.isOperator" type="danger" link size="small" @click="handleDelete(row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    
    <!-- 分页 -->
    <div style="margin-top: 20px; display: flex; justify-content: flex-end">
      <el-pagination
        v-model:current-page="query.page"
        :page-size="query.size"
        :total="total"
        layout="total, prev, pager, next"
        @current-change="handlePageChange"
      />
    </div>
    
    <!-- 编辑对话框 -->
    <el-dialog 
      v-model="dialogVisible" 
      :title="dialogTitle" 
      width="750px" 
      :lock-scroll="true"
      class="config-dialog"
    >
      <el-form ref="formRef" :model="form" :rules="rules" label-width="120px" class="config-form">
        <el-form-item label="租户" prop="tenant_id">
          <el-select 
            v-model="form.tenant_id" 
            :disabled="!!editingId" 
            placeholder="请选择租户"
            filterable
            style="width: 100%"
          >
            <el-option 
              v-for="tenant in tenantList" 
              :key="tenant.code" 
              :label="`${tenant.name} (${tenant.code})`" 
              :value="tenant.code" 
            />
          </el-select>
        </el-form-item>
        <el-form-item label="应用" prop="app_code">
          <el-select v-model="form.app_code" :disabled="!!editingId" placeholder="选择要订阅的应用" style="width: 100%">
            <el-option v-for="app in appList" :key="app.app_code" :label="`${app.app_name} (${app.app_code})`" :value="app.app_code" />
          </el-select>
        </el-form-item>
        <el-form-item label="备注名称">
          <el-input v-model="form.app_name" placeholder="可选，用于区分同应用多配置" />
        </el-form-item>
        
        <template v-if="currentAppRequireJssdk">
          <el-divider content-position="left">企业微信关联</el-divider>
          
          <el-form-item label="关联企微应用">
            <el-select 
              v-model="form.wechat_app_id" 
              placeholder="选择企微应用" 
              clearable 
              style="width: 100%"
            >
              <el-option 
                v-for="wa in wechatAppList" 
                :key="wa.id" 
                :label="`${wa.name} (${wa.corp_id})`" 
                :value="wa.id" 
              />
            </el-select>
            <div v-if="wechatAppList.length === 0 && form.tenant_id" style="color: #909399; font-size: 12px; margin-top: 4px">
              该租户暂无企微应用，请先在「企微应用」中配置
            </div>
          </el-form-item>
        </template>
        
        <!-- 自定义配置 -->
        <template v-if="currentConfigSchema.length > 0 || form.custom_configs.length > 0">
          <el-divider content-position="left">应用配置</el-divider>
          
          <div class="custom-configs-section">
            <!-- 根据 schema 渲染表单 -->
            <template v-for="(schema, index) in currentConfigSchema" :key="schema.key">
              <div class="config-item-schema">
                <div class="config-label">
                  {{ schema.label }}
                  <span v-if="schema.required" class="required-star">*</span>
                </div>
                
                <!-- text 类型 - 短文本直接编辑，长文本用弹窗 -->
                <template v-if="schema.type === 'text'">
                  <!-- 长文本使用预览+弹窗编辑 -->
                  <div 
                    v-if="isLongText(form.custom_configs[index]?.value) || schema.key?.includes('prompt')"
                    class="text-preview-container"
                  >
                    <div class="text-preview" @click="openTextEdit(index, schema)">
                      {{ getTextPreview(form.custom_configs[index]?.value, 100) }}
                    </div>
                    <el-button 
                      type="primary" 
                      size="small" 
                      @click="openTextEdit(index, schema)"
                    >
                      <el-icon><Edit /></el-icon>
                      编辑
                    </el-button>
                  </div>
                  <!-- 短文本直接编辑 -->
                  <el-input
                    v-else
                    v-model="form.custom_configs[index].value"
                    type="textarea"
                    :rows="2"
                    :autosize="{ minRows: 1, maxRows: 4 }"
                    :placeholder="schema.placeholder || '请输入'"
                  />
                </template>
                
                <!-- radio 类型 -->
                <template v-else-if="schema.type === 'radio'">
                  <el-radio-group v-model="form.custom_configs[index].value">
                    <el-radio 
                      v-for="opt in schema.options" 
                      :key="opt" 
                      :value="opt"
                    >
                      {{ getOptionLabel(schema, opt) }}
                    </el-radio>
                  </el-radio-group>
                </template>
                
                <!-- select 类型 -->
                <template v-else-if="schema.type === 'select'">
                  <el-select v-model="form.custom_configs[index].value" placeholder="请选择" style="width: 100%">
                    <el-option 
                      v-for="opt in schema.options" 
                      :key="opt" 
                      :label="getOptionLabel(schema, opt)" 
                      :value="opt" 
                    />
                  </el-select>
                </template>
                
                <!-- switch 类型 -->
                <template v-else-if="schema.type === 'switch'">
                  <el-switch 
                    v-model="form.custom_configs[index].value" 
                    active-value="true" 
                    inactive-value="false"
                  />
                </template>
                
                <!-- 备注输入 -->
                <el-input
                  v-model="form.custom_configs[index].remark"
                  placeholder="备注（可选）"
                  style="margin-top: 8px; width: 300px"
                  size="small"
                />
              </div>
            </template>
            
            <!-- 没有 schema 定义时显示手动配置 -->
            <template v-if="currentConfigSchema.length === 0">
              <div v-for="(config, index) in form.custom_configs" :key="index" class="config-item">
                <div class="config-row">
                  <el-input 
                    v-model="config.key" 
                    placeholder="配置键 (如: industry)"
                    style="width: 150px"
                  />
                  <el-input 
                    v-model="config.remark" 
                    placeholder="备注说明"
                    style="width: 180px; margin-left: 8px"
                  />
                  <el-button 
                    type="danger" 
                    :icon="Delete" 
                    circle 
                    size="small"
                    style="margin-left: 8px"
                    @click="removeCustomConfig(index)"
                  />
                </div>
                <el-input
                  v-model="config.value"
                  type="textarea"
                  :rows="3"
                  :autosize="{ minRows: 2, maxRows: 10 }"
                  placeholder="配置值（支持超长文本，如提示词等）"
                  style="margin-top: 8px"
                />
              </div>
              
              <el-button type="primary" plain @click="addCustomConfig" style="margin-top: 8px">
                <el-icon><Plus /></el-icon>
                添加配置项
              </el-button>
              
              <div v-if="form.custom_configs.length === 0" class="config-empty-tip">
                该应用暂无配置项定义
              </div>
            </template>
          </div>
        </template>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="handleSubmit">确定</el-button>
      </template>
    </el-dialog>
    
    <!-- Token 显示对话框 -->
    <el-dialog v-model="tokenDialogVisible" title="访问 Token" width="600px">
      <div class="token-dialog-content">
        <el-alert type="warning" :closable="false" style="margin-bottom: 16px">
          请妥善保管 Token，它是应用访问平台的凭证
        </el-alert>
        
        <div class="token-section">
          <div class="token-label">Access Token:</div>
          <el-input v-model="currentToken" readonly>
            <template #append>
              <el-button @click="handleCopyToken">复制</el-button>
            </template>
          </el-input>
        </div>
        
        <div v-if="currentAppUrl" class="token-section">
          <div class="token-label">完整访问链接:</div>
          <el-input :model-value="`${currentAppUrl}?token=${currentToken}`" readonly type="textarea" :rows="2" />
          <el-button type="primary" style="margin-top: 8px" @click="handleCopyUrl">
            <el-icon><CopyDocument /></el-icon>
            复制链接
          </el-button>
        </div>
        
        <el-divider />
        
        <div class="token-section">
          <div class="token-label">验证 API:</div>
          <el-input 
            model-value="POST /api/auth/verify" 
            readonly
          />
          <div style="color: #909399; font-size: 12px; margin-top: 4px">
            外部应用可调用此接口验证 Token 有效性，获取租户和企微配置
          </div>
        </div>
      </div>
      <template #footer>
        <el-button @click="tokenDialogVisible = false">关闭</el-button>
      </template>
    </el-dialog>
    
    <!-- 批量添加对话框 -->
    <el-dialog v-model="batchDialogVisible" title="批量添加应用订阅" width="600px">
      <el-form label-width="100px">
        <el-form-item label="选择租户" required>
          <el-select 
            v-model="batchForm.tenant_id" 
            placeholder="请选择租户"
            filterable
            style="width: 100%"
          >
            <el-option 
              v-for="tenant in tenantList" 
              :key="tenant.code" 
              :label="`${tenant.name} (${tenant.code})`" 
              :value="tenant.code" 
            />
          </el-select>
        </el-form-item>
        
        <el-form-item label="选择应用" required>
          <div class="batch-apps-container">
            <div class="batch-apps-header">
              <el-checkbox 
                :model-value="isAllSelected"
                :indeterminate="isIndeterminate"
                @change="toggleSelectAll"
                :disabled="!batchForm.tenant_id || availableAppsForBatch.length === 0"
              >
                全选 ({{ batchForm.selected_apps.length }}/{{ availableAppsForBatch.length }})
              </el-checkbox>
            </div>
            
            <el-empty 
              v-if="!batchForm.tenant_id" 
              description="请先选择租户" 
              :image-size="60"
            />
            <el-empty 
              v-else-if="availableAppsForBatch.length === 0" 
              description="该租户已订阅所有应用" 
              :image-size="60"
            />
            <el-checkbox-group 
              v-else
              v-model="batchForm.selected_apps" 
              class="batch-apps-list"
            >
              <el-checkbox 
                v-for="app in availableAppsForBatch" 
                :key="app.app_code"
                :value="app.app_code"
                class="batch-app-item"
              >
                {{ app.app_name }}
                <span class="app-code">({{ app.app_code }})</span>
              </el-checkbox>
            </el-checkbox-group>
          </div>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="batchDialogVisible = false">取消</el-button>
        <el-button 
          type="primary" 
          :loading="batchLoading"
          :disabled="!batchForm.tenant_id || batchForm.selected_apps.length === 0"
          @click="handleBatchSubmit"
        >
          创建 {{ batchForm.selected_apps.length }} 个订阅
        </el-button>
      </template>
    </el-dialog>
    
    <!-- 批量 Token 结果对话框 -->
    <el-dialog v-model="batchTokenDialogVisible" title="批量创建成功" width="700px">
      <el-alert type="success" :closable="false" style="margin-bottom: 16px">
        已成功创建 {{ batchTokenList.length }} 个应用订阅，以下是访问链接：
      </el-alert>
      
      <div class="batch-token-list">
        <div 
          v-for="item in batchTokenList" 
          :key="item.app_code"
          class="batch-token-item"
        >
          <div class="batch-token-info">
            <span class="batch-token-name">{{ item.app_name }}</span>
            <el-tag v-if="!item.base_url" type="warning" size="small">无链接</el-tag>
          </div>
          <div v-if="item.base_url" class="batch-token-url">
            {{ item.base_url }}?token={{ item.token.slice(0, 20) }}...
          </div>
          <el-button 
            v-if="item.base_url"
            type="primary" 
            size="small" 
            @click="copyBatchTokenLink(item)"
          >
            <el-icon><CopyDocument /></el-icon>
            复制
          </el-button>
        </div>
      </div>
      
      <template #footer>
        <el-button @click="copyAllTokenLinks" type="success">
          <el-icon><CopyDocument /></el-icon>
          复制全部链接
        </el-button>
        <el-button @click="batchTokenDialogVisible = false">关闭</el-button>
      </template>
    </el-dialog>
    
    <!-- 长文本编辑弹窗 - 接近全屏 -->
    <el-dialog 
      v-model="textEditDialogVisible" 
      :title="`编辑：${textEditData.label}`" 
      width="90vw"
      top="5vh"
      :close-on-click-modal="false"
      :lock-scroll="true"
      :append-to-body="true"
      class="text-edit-dialog"
    >
      <div class="text-edit-wrapper">
        <el-input
          v-model="textEditData.value"
          type="textarea"
          :placeholder="textEditData.placeholder"
          class="text-edit-textarea"
          resize="none"
        />
      </div>
      <div class="text-edit-stats">
        字符数：{{ textEditData.value?.length || 0 }}
      </div>
      <template #footer>
        <el-button @click="textEditDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="saveTextEdit">保存</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<style scoped>
.page-tip {
  margin-bottom: 16px;
}

/* 租户标签筛选 */
.tenant-tags {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 16px;
  padding: 12px 16px;
  background: #f5f7fa;
  border-radius: 8px;
}

.tag-label {
  color: #606266;
  font-size: 13px;
  font-weight: 500;
  margin-right: 4px;
}

.tenant-tag {
  cursor: pointer;
  transition: all 0.2s;
}

.tenant-tag:hover {
  transform: translateY(-1px);
}

.clear-tag {
  margin-left: 8px;
}

.cell-name {
  font-weight: 500;
  color: #303133;
}

.header-actions {
  display: flex;
  gap: 10px;
}

/* 批量添加对话框样式 */
.batch-apps-container {
  border: 1px solid #dcdfe6;
  border-radius: 8px;
  padding: 12px;
  background: #fafafa;
}

.batch-apps-header {
  padding-bottom: 12px;
  border-bottom: 1px solid #ebeef5;
  margin-bottom: 12px;
}

.batch-apps-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 300px;
  overflow-y: auto;
}

.batch-app-item {
  display: flex;
  align-items: center;
  padding: 8px 12px;
  background: white;
  border-radius: 6px;
  border: 1px solid #ebeef5;
  transition: all 0.2s;
}

.batch-app-item:hover {
  border-color: #409eff;
}

.app-code {
  color: #909399;
  font-size: 12px;
  margin-left: 4px;
}

/* 批量 Token 结果样式 */
.batch-token-list {
  max-height: 400px;
  overflow-y: auto;
}

.batch-token-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px;
  background: #f5f7fa;
  border-radius: 8px;
  margin-bottom: 8px;
}

.batch-token-item:last-child {
  margin-bottom: 0;
}

.batch-token-info {
  display: flex;
  align-items: center;
  gap: 8px;
}

.batch-token-name {
  font-weight: 500;
  color: #303133;
}

.batch-token-url {
  flex: 1;
  color: #909399;
  font-size: 12px;
  margin: 0 16px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 长文本预览样式 */
.text-preview-container {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}

.text-preview {
  flex: 1;
  padding: 10px 12px;
  background: #f5f7fa;
  border: 1px solid #dcdfe6;
  border-radius: 6px;
  color: #606266;
  font-size: 13px;
  line-height: 1.5;
  cursor: pointer;
  transition: all 0.2s;
  min-height: 40px;
  max-height: 80px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: pre-wrap;
  word-break: break-all;
}

.text-preview:hover {
  border-color: #409eff;
  background: #ecf5ff;
}

/* 长文本编辑弹窗样式 - 接近全屏 */
.text-edit-dialog :deep(.el-dialog) {
  max-width: 1200px;
  margin: 0 auto;
}

.text-edit-dialog :deep(.el-dialog__body) {
  padding: 16px 20px;
}

.text-edit-wrapper {
  height: calc(70vh - 60px);
}

.text-edit-wrapper :deep(.el-textarea) {
  height: 100%;
}

.text-edit-wrapper :deep(.el-textarea__inner) {
  font-family: 'Monaco', 'Menlo', 'Consolas', monospace;
  font-size: 14px;
  line-height: 1.7;
  height: 100% !important;
  resize: none;
  padding: 16px;
}

.text-edit-stats {
  margin-top: 12px;
  text-align: right;
  color: #909399;
  font-size: 12px;
}

/* 配置对话框优化 */
.config-dialog :deep(.el-dialog__body) {
  max-height: 60vh;
  overflow-y: auto;
  padding-right: 20px;
}

.config-form {
  padding-right: 10px;
}

.token-dialog-content {
  padding: 0 10px;
}

.token-section {
  margin-bottom: 16px;
}

.token-label {
  font-weight: 500;
  margin-bottom: 8px;
  color: #303133;
}

/* 自定义配置样式 */
.custom-configs-section {
  padding: 0 10px;
}

.config-item {
  background: #f5f7fa;
  border-radius: 8px;
  padding: 12px;
  margin-bottom: 12px;
}

.config-item-schema {
  background: #f5f7fa;
  border-radius: 8px;
  padding: 16px;
  margin-bottom: 12px;
}

.config-label {
  font-weight: 500;
  color: #303133;
  margin-bottom: 10px;
  font-size: 14px;
}

.required-star {
  color: #f56c6c;
  margin-left: 4px;
}

.config-row {
  display: flex;
  align-items: center;
}

.config-empty-tip {
  color: #909399;
  font-size: 13px;
  text-align: center;
  padding: 20px 0;
}
</style>
