<template>
  <div class="app-list-container">
    <div class="header">
      <h2>应用管理</h2>
      <div class="header-actions">
          <el-input 
            v-model="searchQuery" 
            placeholder="搜索应用名称或 AppID" 
            style="width: 250px; margin-right: 10px;"
            clearable
            @clear="fetchApps"
            @keyup.enter="handleSearch"
          >
            <template #append>
              <el-button icon="Search" @click="handleSearch" />
            </template>
          </el-input>
          <el-button type="primary" @click="openCreateDialog">创建应用</el-button>
      </div>
    </div>

    <el-table :data="apps" v-loading="loading" style="width: 100%" stripe border>
      <el-table-column prop="id" label="ID" width="80" />
      <el-table-column label="Logo" width="76" align="center">
        <template #default="scope">
          <div v-if="scope.row.icon_url" class="logo-cell">
            <PlatformIcon
              :text="scope.row.app_name"
              :size="40"
              :icon-url="scope.row.icon_url"
              :app-id="scope.row.app_id"
              :icon-object-key="scope.row.icon_object_key"
              :show-caption="false"
            />
          </div>
          <span v-else class="logo-placeholder">—</span>
        </template>
      </el-table-column>
      <el-table-column prop="app_name" label="应用名称" min-width="150" />
      <el-table-column prop="app_id" label="App ID" min-width="220" />
      <el-table-column prop="protocol_type" label="协议类型" width="140">
        <template #default="scope">
          <el-tag :type="protocolTagType(scope.row.protocol_type)">
            {{ scope.row.protocol_type === 'NONE' ? '无' : scope.row.protocol_type }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="300" fixed="right">
        <template #default="scope">
          <div class="action-buttons">
            <el-button type="primary" link @click="handleEdit(scope.row)">编辑</el-button>
            <el-divider direction="vertical" />
            <el-button type="primary" link @click="handleMapping(scope.row)">账号映射</el-button>
            <template v-if="user && (user.role === 'SUPER_ADMIN' || scope.row.owner_id === user.id)">
              <el-divider direction="vertical" />
              <el-button type="primary" link @click="handleViewSecret(scope.row)">密钥</el-button>
              <el-divider direction="vertical" />
              
              <el-dropdown trigger="click">
                <span class="el-dropdown-link">
                  更多<el-icon class="el-icon--right"><arrow-down /></el-icon>
                </span>
                <template #dropdown>
                  <el-dropdown-menu>
                    <el-dropdown-item @click="handleSyncUsers(scope.row)">用户数据同步</el-dropdown-item>
                    <el-dropdown-item @click="handleRegenerate(scope.row)">重置密钥</el-dropdown-item>
                    <el-dropdown-item @click="handleTransfer(scope.row)">应用转让</el-dropdown-item>
                    <el-dropdown-item @click="handleLogs(scope.row)">操作日志</el-dropdown-item>
                  </el-dropdown-menu>
                </template>
              </el-dropdown>
            </template>
          </div>
        </template>
      </el-table-column>
    </el-table>

    <div class="pagination">
      <el-pagination
        v-model:current-page="currentPage"
        v-model:page-size="pageSize"
        :page-sizes="[10, 20, 50, 100]"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </div>

    <!-- Create/Edit Dialog -->
    <el-dialog v-model="dialogVisible" :title="isEdit ? '编辑应用' : '创建应用'" width="500px">
      <el-form :model="form" label-width="100px">
        <el-form-item label="应用名称">
          <el-input v-model="form.app_name" />
        </el-form-item>
        <el-form-item label="应用分类">
          <el-select 
            v-model="form.category_id" 
            placeholder="请选择分类"
            filterable
            clearable
            style="width: 100%"
          >
            <el-option
              v-for="cat in presetCategories"
              :key="cat.id"
              :label="cat.name"
              :value="cat.id"
            >
              <span>{{ cat.name }}</span>
              <span v-if="cat.description" style="color: #8492a6; font-size: 12px; margin-left: 10px;">
                {{ cat.description }}
              </span>
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="应用描述">
          <el-input 
            v-model="form.description" 
            type="textarea" 
            :rows="3"
            placeholder="请输入应用描述（选填）"
            maxlength="500"
            show-word-limit
          />
        </el-form-item>
        <el-form-item label="协议类型">
          <el-select v-model="form.protocol_type">
            <el-option label="简易 API (Ticket)" value="SIMPLE_API" />
            <el-option label="OIDC 标准协议" value="OIDC" />
            <el-option label="无（仅导航）" value="NONE" />
          </el-select>
        </el-form-item>
        <el-form-item label="回调地址">
          <el-input v-model="form.redirect_uris" :placeholder="redirectUriPlaceholder" />
        </el-form-item>
        <el-form-item label="Webhook">
          <el-input v-model="form.notification_url" />
        </el-form-item>
        <el-form-item label="应用 Logo">
          <el-upload
            :auto-upload="false"
            :limit="1"
            :on-change="onAppIconChange"
            :on-remove="onAppIconRemove"
            :file-list="iconFileList"
            accept="image/png,image/jpeg,image/gif,image/webp"
          >
            <el-button type="primary" :loading="iconUploading">选择图标</el-button>
            <template #tip>
              <span class="tip">PNG、JPG、GIF、WebP，最大 2MB；保存后写入应用</span>
            </template>
          </el-upload>
          <img v-if="iconPreview" :src="iconPreview" class="icon-preview" alt="" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="handleSubmit">确定</el-button>
        </span>
      </template>
    </el-dialog>

    <!-- Verify Password Dialog for Viewing Secret -->
    <el-dialog v-model="verifyDialogVisible" title="安全验证" width="400px">
      <p>查看密钥需要验证管理员密码。</p>
      <el-input
        v-model="adminPassword"
        type="password"
        placeholder="请输入管理员密码"
        show-password
        @keyup.enter="confirmViewSecret"
      />
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="verifyDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="confirmViewSecret" :loading="verifying">验证</el-button>
        </span>
      </template>
    </el-dialog>

    <!-- Secret Display Dialog -->
    <el-dialog v-model="secretDialogVisible" title="应用凭证" width="500px">
      <div class="secret-box">
        <p v-if="secretIsNew">请立即复制保存以下凭证。密钥仅显示一次，无法再次查看。</p>
        <div class="credential-item">
          <strong>App ID:</strong>
          <span>{{ secretData.app_id }}</span>
        </div>
        <div class="credential-item">
          <strong>App Secret:</strong>
          <span class="secret-text">{{ secretData.app_secret }}</span>
        </div>
        <div class="credential-item" v-if="secretData.access_token">
          <strong>Access Token (永久):</strong>
          <div class="token-text">{{ secretData.access_token }}</div>
        </div>
      </div>
      <template #footer>
        <el-button type="primary" @click="secretDialogVisible = false">关闭</el-button>
      </template>
    </el-dialog>
    <!-- Security Verification Dialog -->
    <el-dialog v-model="securityDialogVisible" title="安全验证" width="450px" :close-on-click-modal="false">
      <el-alert title="敏感操作需要验证身份" type="warning" :closable="false" style="margin-bottom: 20px;" />
      <div v-if="securityAction === 'EDIT' && user && user.mobile" style="margin-bottom: 15px; color: #666; font-size: 14px; text-align: center;">
          验证码将发送至您绑定的手机号：<strong>{{ user.mobile.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2') }}</strong>
      </div>
      <el-form :model="securityForm" label-width="100px">
        <el-form-item label="验证码" required>
            <div style="display: flex; gap: 10px; width: 100%;">
                <el-input v-model="securityForm.verificationCode" placeholder="手机验证码" />
                <el-button type="primary" plain :disabled="cooldown > 0" @click="sendCode">
                    {{ cooldown > 0 ? `${cooldown}s` : '发送' }}
                </el-button>
            </div>
        </el-form-item>
        <el-form-item label="管理员密码" required v-if="securityAction !== 'EDIT'">
          <el-input 
            v-model="securityForm.password" 
            type="password" 
            placeholder="请输入您的登录密码" 
            show-password 
            :name="dynamicFields.password"
            autocomplete="new-password"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="securityDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="confirmSecurityAction" :loading="processing">确定</el-button>
        </span>
      </template>
    </el-dialog>

    <!-- Transfer Dialog -->
    <el-dialog v-model="transferDialogVisible" title="应用转让" width="450px" :close-on-click-modal="false">
      <el-alert title="将应用管理权限完全转让给其他用户，操作后您将失去管理权限。" type="error" :closable="false" style="margin-bottom: 20px;" />
      <el-form :model="transferForm" label-width="100px">
        <el-form-item label="当前拥有者">
          <span>{{ transferOwnerName }}</span>
        </el-form-item>
        <el-form-item label="目标用户" required>
            <el-select
                v-model="transferForm.targetMobile"
                filterable
                remote
                reserve-keyword
                placeholder="手机号或姓名搜索（仅开发者/超管）"
                :remote-method="handleUserSearch"
                :loading="userLoading"
                style="width: 100%"
            >
                <el-option
                    v-for="item in userOptions"
                    :key="item.id"
                    :label="`${item.name || item.mobile} · ${item.mobile} (${item.role})`"
                    :value="item.mobile"
                />
            </el-select>
        </el-form-item>
        <el-form-item label="验证码" required>
            <div style="display: flex; gap: 10px; width: 100%;">
                <el-input v-model="transferForm.verificationCode" placeholder="手机验证码 (发送至您的手机)" />
                <el-button type="primary" plain :disabled="cooldown > 0" @click="sendCode">
                    {{ cooldown > 0 ? `${cooldown}s` : '发送' }}
                </el-button>
            </div>
        </el-form-item>
        <el-form-item label="管理员密码" required>
          <el-input 
            v-model="transferForm.password" 
            type="password" 
            placeholder="请输入您的登录密码" 
            show-password 
            :name="transferDynamicFields.password"
            autocomplete="new-password"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="transferDialogVisible = false">取消</el-button>
          <el-button type="danger" @click="confirmTransfer" :loading="transferring">确认转让</el-button>
        </span>
      </template>
    </el-dialog>

    <!-- Logs Dialog -->
    <el-dialog v-model="logsDialogVisible" title="操作日志" width="900px">
        <div class="logs-toolbar" style="margin-bottom: 15px; display: flex; gap: 10px; flex-wrap: wrap;">
            <el-select v-model="logsParams.action_type" placeholder="操作类型" clearable style="width: 150px" @change="fetchLogs">
                <el-option label="手动添加映射" value="MANUAL_ADD" />
                <el-option label="删除映射" value="DELETE" />
                <el-option label="更新映射" value="UPDATE" />
                <el-option label="批量导入" value="IMPORT" />
                <el-option label="同步用户" value="SYNC" />
                <el-option label="M2M 账号同步" value="SYNC_M2M" />
                <el-option label="应用转让" value="TRANSFER" />
                <el-option label="查看密钥" value="VIEW_SECRET" />
                <el-option label="重置密钥" value="REGENERATE_SECRET" />
            </el-select>
            <el-input v-model="logsParams.keyword" placeholder="搜索手机号" style="width: 200px" clearable @clear="fetchLogs" @keyup.enter="fetchLogs" />
            <el-date-picker
                v-model="logsParams.dateRange"
                type="daterange"
                range-separator="至"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
                value-format="YYYY-MM-DD"
                @change="fetchLogs"
                style="width: 240px"
            />
            <el-button type="primary" icon="Search" @click="fetchLogs">查询</el-button>
        </div>

        <el-table :data="logsData" v-loading="logsLoading" border stripe height="500">
            <el-table-column prop="id" label="ID" width="70" />
            <el-table-column prop="operator_mobile" label="操作人" width="120" />
            <el-table-column prop="action_type" label="操作类型" width="120">
                <template #default="scope">
                    <el-tag>{{ formatActionType(scope.row.action_type) }}</el-tag>
                </template>
            </el-table-column>
            <el-table-column prop="target_mobile" label="目标用户" width="120">
                 <template #default="scope">
                    {{ scope.row.target_mobile || '-' }}
                </template>
            </el-table-column>
            <el-table-column prop="ip_address" label="来源 IP" width="130">
                <template #default="scope">
                    {{ scope.row.ip_address || '-' }}
                </template>
            </el-table-column>
            <el-table-column prop="details" label="详情" min-width="200">
                <template #default="scope">
                    <el-popover placement="top-start" :width="400" trigger="hover" v-if="scope.row.details">
                        <template #reference>
                            <span style="cursor: pointer; color: #409eff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block;">
                                {{ formatLogDetail(scope.row.details) }}
                            </span>
                        </template>
                        <pre style="max-height: 300px; overflow: auto; font-size: 12px;">{{ formatLogDetail(scope.row.details) }}</pre>
                    </el-popover>
                    <span v-else>-</span>
                </template>
            </el-table-column>
            <el-table-column prop="created_at" label="操作时间" width="170">
                <template #default="scope">
                    {{ new Date(scope.row.created_at).toLocaleString() }}
                </template>
            </el-table-column>
        </el-table>

        <div style="margin-top: 15px; display: flex; justify-content: flex-end;">
            <el-pagination
                v-model:current-page="logsParams.page"
                v-model:page-size="logsParams.pageSize"
                layout="total, prev, pager, next"
                :total="logsTotal"
                @current-change="handleLogsPageChange"
            />
        </div>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, reactive, computed, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
import { useAuthStore } from '../../store/auth'
import { 
  getApps, createApp, updateApp, deleteApp, regenerateSecret, viewSecret, transferApp, getOperationLogs,
  getPresetCategories, uploadAppIcon,
  Application, ApplicationCreate, OperationLog, AppCategory
} from '../../api/apps'
import { searchUsers, getUserById, User } from '../../api/users'
import { sendImportVerificationCode } from '../../api/mapping'
import { ElMessage, ElMessageBox } from 'element-plus'
import { ArrowDown, Search } from '@element-plus/icons-vue'
import PlatformIcon from '../../components/PlatformIcon.vue'

const router = useRouter()
const authStore = useAuthStore()
const user = computed(() => authStore.user)

const protocolTagType = (p: string) => {
  if (p === 'OIDC') return 'success'
  if (p === 'NONE') return 'info'
  return 'warning'
}

const redirectUriPlaceholder = computed(() =>
  form.protocol_type === 'NONE'
    ? '导航目标完整 URL（http(s)://...），快捷跳转不携带 ticket'
    : 'JSON 列表或逗号分隔'
)

// Data
const apps = ref<Application[]>([])
const loading = ref(false)
const total = ref(0)
const currentPage = ref(1)
const pageSize = ref(10)
const searchQuery = ref('')
const presetCategories = ref<AppCategory[]>([])

// Dialogs
const dialogVisible = ref(false)
const secretDialogVisible = ref(false)
const verifyDialogVisible = ref(false)
const isEdit = ref(false)
const secretIsNew = ref(false)
const currentId = ref<number | null>(null)
const viewingAppId = ref<number | null>(null)
const adminPassword = ref('')
const verifying = ref(false)

// Security Dialog
const securityDialogVisible = ref(false)
const processing = ref(false)
const securityAction = ref<'EDIT' | 'REGENERATE'>('EDIT')
const securityForm = reactive({
    verificationCode: '',
    password: ''
})
const dynamicFields = reactive({
  password: 'admin_password'
})
const cooldown = ref(0)
let timer: any = null

const form = reactive<ApplicationCreate>({
  app_name: '',
  protocol_type: 'SIMPLE_API',
  redirect_uris: '',
  notification_url: '',
  description: '',
  category_id: undefined
})

const pendingIconKey = ref('')
const iconPreview = ref('')
const iconFileList = ref<{ name: string; uid: string }[]>([])
const iconUploading = ref(false)
/** 用户修改过 Logo 后再带上 icon_url，避免误清空仅外链存储的场景 */
const iconTouched = ref(false)

const secretData = reactive({
  app_id: '',
  app_secret: '',
  access_token: ''
})

// ===== 工具函数：回调地址校验 =====
const isValidUrl = (u: string) => {
  try {
    const url = new URL(u)
    return url.protocol === 'http:' || url.protocol === 'https:'
  } catch {
    return false
  }
}

const validateRedirectUris = (raw: string): boolean => {
  if (!raw || !raw.trim()) return true // 允许为空

  // 1. 先尝试 JSON 解析
  try {
    const parsed = JSON.parse(raw)
    if (Array.isArray(parsed)) {
      return parsed.every(x => typeof x === 'string' && isValidUrl(x.trim()))
    }
    if (typeof parsed === 'string') {
      return isValidUrl(parsed.trim())
    }
  } catch {
    // 2. 非 JSON 时，当作逗号分隔 / 单个 URL
    const parts = raw.split(',').map(x => x.trim()).filter(Boolean)
    if (parts.length === 0) return true
    return parts.every(isValidUrl)
  }

  return false
}

// Methods
const fetchPresetCategories = async () => {
  try {
    const res = await getPresetCategories()
    presetCategories.value = res.data
  } catch (error) {
    console.error(error)
  }
}

const fetchApps = async () => {
  loading.value = true
  try {
    const skip = (currentPage.value - 1) * pageSize.value
    const res = await getApps(skip, pageSize.value, searchQuery.value)
    apps.value = res.data.items
    total.value = res.data.total
  } catch (error) {
    console.error(error)
  } finally {
    loading.value = false
  }
}

const handleSearch = () => {
    currentPage.value = 1
    fetchApps()
}

const handleSizeChange = (val: number) => {
  pageSize.value = val
  fetchApps()
}

const handleCurrentChange = (val: number) => {
  currentPage.value = val
  fetchApps()
}

// Create / Edit
const openCreateDialog = () => {
  isEdit.value = false
  currentId.value = null
  form.app_name = ''
  form.protocol_type = 'SIMPLE_API'
  form.redirect_uris = ''
  form.notification_url = ''
  form.description = ''
  form.category_id = undefined
  pendingIconKey.value = ''
  iconPreview.value = ''
  iconFileList.value = []
  iconTouched.value = false
  dialogVisible.value = true
}

const onAppIconChange = async (file: { raw?: File; uid: string }) => {
  const raw = file.raw
  if (!raw) return
  if (raw.size > 2 * 1024 * 1024) {
    ElMessage.warning('图标大小不能超过 2MB')
    return
  }
  const uploadAsAppId = isEdit.value && currentId.value ? currentId.value : 0
  iconUploading.value = true
  try {
    const res = await uploadAppIcon(raw, uploadAsAppId)
    pendingIconKey.value = res.data.object_key
    iconPreview.value = URL.createObjectURL(raw)
    iconFileList.value = [{ name: raw.name, uid: file.uid }]
    iconTouched.value = true
  } catch {
    iconFileList.value = []
  } finally {
    iconUploading.value = false
  }
}

const onAppIconRemove = () => {
  pendingIconKey.value = ''
  iconPreview.value = ''
  iconFileList.value = []
  iconTouched.value = true
}

const handleEdit = (row: Application) => {
  isEdit.value = true
  currentId.value = row.id
  form.app_name = row.app_name
  form.protocol_type = row.protocol_type
  form.redirect_uris = row.redirect_uris || ''
  form.notification_url = row.notification_url || ''
  form.description = row.description || ''
  form.category_id = row.category_id
  pendingIconKey.value = row.icon_object_key || ''
  iconPreview.value = row.icon_url || ''
  iconFileList.value = row.icon_url ? [{ name: '当前图标', uid: 'current' }] : []
  iconTouched.value = false
  dialogVisible.value = true
}

const handleSubmit = async () => {
  try {
    if (form.protocol_type === 'NONE' && (!form.redirect_uris || !String(form.redirect_uris).trim())) {
      ElMessage.error('导航类应用请填写导航目标 URL（回调地址）')
      return
    }
    // 校验回调地址合法性
    if (!validateRedirectUris(form.redirect_uris || '')) {
      ElMessage.error('回调地址格式不合法，请填写以 http/https 开头的完整 URL，可用逗号分隔多个或 JSON 列表')
      return
    }

    if (isEdit.value && currentId.value) {
      // For Edit, open security dialog
      securityAction.value = 'EDIT'
      openSecurityDialog()
    } else {
      const res = await createApp({
        ...form,
        icon_url: pendingIconKey.value || undefined
      })
      secretData.app_id = res.data.app_id
      secretData.app_secret = res.data.app_secret
      secretData.access_token = res.data.access_token
      secretIsNew.value = true
      secretDialogVisible.value = true
      dialogVisible.value = false
      fetchApps()
    }
  } catch (error) {
    // handled by interceptor
  }
}

const openSecurityDialog = () => {
    securityForm.verificationCode = ''
    securityForm.password = ''
    // Randomize field name
    const randomSuffix = Math.random().toString(36).slice(2, 8)
    dynamicFields.password = `pwd_${randomSuffix}`
    
    securityDialogVisible.value = true
}

const sendCode = async () => {
    try {
        await sendImportVerificationCode()
        ElMessage.success('验证码已发送')
        cooldown.value = 60
        timer = setInterval(() => {
            cooldown.value--
            if (cooldown.value <= 0) {
                clearInterval(timer)
            }
        }, 1000)
    } catch (e) {
        // handled
    }
}

const confirmSecurityAction = async () => {
    // Validate password only if not EDIT
    if (!securityForm.verificationCode || (securityAction.value !== 'EDIT' && !securityForm.password)) {
        ElMessage.warning(securityAction.value === 'EDIT' ? '请填写验证码' : '请填写验证码和密码')
        return
    }
    
    processing.value = true
    try {
        if (securityAction.value === 'EDIT' && currentId.value) {
            // 编辑时再次校验回调地址
            if (form.protocol_type === 'NONE' && (!form.redirect_uris || !String(form.redirect_uris).trim())) {
                ElMessage.error('导航类应用请填写导航目标 URL（回调地址）')
                processing.value = false
                return
            }
            if (!validateRedirectUris(form.redirect_uris || '')) {
                ElMessage.error('回调地址格式不合法，请填写以 http/https 开头的完整 URL，可用逗号分隔多个或 JSON 列表')
                processing.value = false
                return
            }
            // Merge form data with security data (exclude password)
            const updatePayload: Record<string, unknown> = {
                ...form,
                verification_code: securityForm.verificationCode
            }
            if (iconTouched.value) {
                updatePayload.icon_url = pendingIconKey.value
            }
            await updateApp(currentId.value, updatePayload as Partial<ApplicationCreate> & { verification_code: string })
            ElMessage.success('更新成功')
            dialogVisible.value = false // close edit dialog
            securityDialogVisible.value = false
            fetchApps()
        } else if (securityAction.value === 'REGENERATE' && currentId.value) {
             const res = await regenerateSecret(currentId.value, {
                 password: securityForm.password,
                 verification_code: securityForm.verificationCode
             })
            secretData.app_id = res.data.app_id
            secretData.app_secret = res.data.app_secret
            secretData.access_token = res.data.access_token
            secretIsNew.value = true
            secretDialogVisible.value = true
            securityDialogVisible.value = false
        }
    } catch (e: any) {
        if (e.response && (e.response.status === 401 || e.response.status === 400)) {
             ElMessage.error(e.response.data.detail || '验证失败')
        }
    } finally {
        processing.value = false
    }
}

onUnmounted(() => {
    if (timer) clearInterval(timer)
})

// View Secret
const handleViewSecret = (row: Application) => {
  viewingAppId.value = row.id
  adminPassword.value = ''
  verifyDialogVisible.value = true
}

const confirmViewSecret = async () => {
  if (!adminPassword.value) {
    ElMessage.warning('请输入密码')
    return
  }
  verifying.value = true
  try {
    const res = await viewSecret(viewingAppId.value!, adminPassword.value)
    secretData.app_id = res.data.app_id
    secretData.app_secret = res.data.app_secret
    secretData.access_token = res.data.access_token
    secretIsNew.value = false
    verifyDialogVisible.value = false
    secretDialogVisible.value = true
  } catch (e) {
    // error handled by interceptor
  } finally {
    verifying.value = false
  }
}

// Regenerate
const handleRegenerate = (row: Application) => {
   currentId.value = row.id // Set current ID for the dialog
   ElMessageBox.confirm('这将导致旧密钥失效。是否继续？', '警告', {
    confirmButtonText: '继续',
    type: 'warning'
  }).then(() => {
    securityAction.value = 'REGENERATE'
    openSecurityDialog()
  })
}

// Transfer
const transferDialogVisible = ref(false)
const transferring = ref(false)
const transferForm = reactive({
    targetMobile: '',
    verificationCode: '',
    password: ''
})
const transferDynamicFields = reactive({
    password: 'transfer_password'
})
const transferOwnerName = ref('')

const TRANSFER_TARGET_ROLES = ['DEVELOPER', 'SUPER_ADMIN']

// Sync Users
const handleSyncUsers = (row: Application) => {
  router.push(`/dashboard/apps/${row.id}/sync`)
}

// Logs
const logsDialogVisible = ref(false)
const logsLoading = ref(false)
const logsData = ref<OperationLog[]>([])
const logsTotal = ref(0)
const logsParams = reactive({
    page: 1,
    pageSize: 20,
    action_type: '',
    keyword: '',
    dateRange: [] as any
})

const handleLogs = (row: Application) => {
    currentId.value = row.id
    logsParams.page = 1
    logsParams.pageSize = 20
    logsParams.action_type = ''
    logsParams.keyword = ''
    logsParams.dateRange = []
    
    logsDialogVisible.value = true
    fetchLogs()
}

const fetchLogs = async () => {
    if (!currentId.value) return
    logsLoading.value = true
    try {
        const skip = (logsParams.page - 1) * logsParams.pageSize
        const params: any = {
            skip, 
            limit: logsParams.pageSize,
            keyword: logsParams.keyword,
            action_type: logsParams.action_type || undefined
        }
        if (logsParams.dateRange && logsParams.dateRange.length === 2) {
            params.start_date = logsParams.dateRange[0]
            params.end_date = logsParams.dateRange[1]
        }
        
        const res = await getOperationLogs(currentId.value, params)
        logsData.value = res.data.items
        logsTotal.value = res.data.total
    } catch (e) {
        console.error(e)
    } finally {
        logsLoading.value = false
    }
}

const handleLogsPageChange = (val: number) => {
    logsParams.page = val
    fetchLogs()
}

const formatLogDetail = (detail: any) => {
    if (!detail) return '-'
    try {
        if (typeof detail === 'string') return detail
        return JSON.stringify(detail, null, 2)
    } catch {
        return '-'
    }
}

const formatActionType = (type: string) => {
    const map: Record<string, string> = {
        'MANUAL_ADD': '手动添加映射',
        'DELETE': '删除映射',
        'UPDATE': '更新映射',
        'IMPORT': '批量导入',
        'SYNC': '同步用户',
        'TRANSFER': '应用转让',
        'VIEW_SECRET': '查看密钥',
        'REGENERATE_SECRET': '重置密钥',
        'SYNC_M2M': 'M2M 同步',
        'DISABLE': '禁用',
        'ENABLE': '启用',
        'RESET_PASSWORD': '重置密码',
        'CHANGE_ROLE': '变更角色'
    }
    return map[type] || type
}

const userOptions = ref<User[]>([])
const userLoading = ref(false)

const handleUserSearch = async (query: string) => {
    userLoading.value = true
    try {
        const res = await searchUsers(query)
        userOptions.value = res.data.filter((u) => TRANSFER_TARGET_ROLES.includes(u.role))
    } catch (e) {
        console.error(e)
    } finally {
        userLoading.value = false
    }
}

const handleTransfer = async (row: Application) => {
    currentId.value = row.id
    transferForm.targetMobile = ''
    transferForm.verificationCode = ''
    transferForm.password = ''
    userOptions.value = []
    transferOwnerName.value = '加载中…'

    const randomSuffix = Math.random().toString(36).slice(2, 8)
    transferDynamicFields.password = `pwd_${randomSuffix}`

    try {
        if (user.value?.id === row.owner_id) {
            const u = user.value
            transferOwnerName.value = u?.name?.trim() || u?.mobile || '—'
        } else {
            const res = await getUserById(row.owner_id)
            const n = res.data.name?.trim()
            transferOwnerName.value = n || res.data.mobile || '—'
        }
    } catch {
        transferOwnerName.value = '—'
    }

    await handleUserSearch('')

    transferDialogVisible.value = true
}

const confirmTransfer = async () => {
    if (!transferForm.targetMobile || !transferForm.password || !transferForm.verificationCode) {
        ElMessage.warning('请填写所有必填项')
        return
    }
    
    transferring.value = true
    try {
        await transferApp(currentId.value!, {
            target_mobile: transferForm.targetMobile,
            password: transferForm.password,
            verification_code: transferForm.verificationCode
        })
        ElMessage.success('应用转让成功')
        transferDialogVisible.value = false
        fetchApps()
    } catch (e: any) {
        if (e.response && e.response.data && e.response.data.detail) {
             ElMessage.error(e.response.data.detail)
        } else {
             ElMessage.error('转让失败')
        }
    } finally {
        transferring.value = false
    }
}

// Mapping
const handleMapping = (row: Application) => {
  router.push({ name: 'MappingImport', params: { id: row.id }, query: { name: row.app_name } })
}

onMounted(() => {
  if (user.value?.role === 'ORDINARY_USER') {
    router.replace('/dashboard/mappings')
    return
  }
  fetchApps()
  fetchPresetCategories()
})
</script>

<style scoped>
.app-list-container {
  padding: 20px;
  background-color: #fff;
  border-radius: 4px;
}
.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}
.header-actions {
    display: flex;
    align-items: center;
}
.pagination {
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
}
.secret-box {
  background: #f4f4f5;
  padding: 15px;
  border-radius: 4px;
}
.credential-item {
  margin-top: 10px;
  font-family: monospace;
}
.secret-text {
  color: #f56c6c;
  font-weight: bold;
}
.token-text {
  color: #67c23a;
  font-weight: bold;
  word-break: break-all;
  margin-top: 5px;
  background: #fff;
  padding: 5px;
  border-radius: 4px;
  border: 1px dashed #dcdfe6;
}
.logo-cell {
  display: flex;
  justify-content: center;
  align-items: center;
}

.logo-cell :deep(.platform-icon-cell) {
  cursor: default;
}

.logo-cell :deep(.platform-icon) {
  border: 1px solid #eee;
}

.logo-placeholder {
  color: #c0c4cc;
  font-size: 14px;
}
.icon-preview {
  margin-top: 8px;
  width: 64px;
  height: 64px;
  object-fit: cover;
  border-radius: 8px;
  border: 1px solid #eee;
}
.tip {
  font-size: 12px;
  color: #999;
  margin-left: 8px;
}
.action-buttons {
  display: flex;
  align-items: center;
  justify-content: flex-start;
}
.el-dropdown-link {
  cursor: pointer;
  color: #409eff;
  display: flex;
  align-items: center;
  font-size: 14px;
  margin-left: 10px;
}
</style>
