<template>
  <div class="perm-page" v-loading="pageLoading">

    <!-- ══════════════════════════════════════
         项目权限配置
    ══════════════════════════════════════ -->
    <template v-if="activeTab === 'project'">
      <div class="perm-header">
        <div class="perm-header-left">
          <h2 class="perm-title">项目权限配置</h2>
          <span class="perm-subtitle">为每个项目的角色配置接口级权限</span>
        </div>
        <div class="perm-header-actions">
          <el-select
            v-model="selectedStudyId"
            placeholder="选择项目"
            filterable
            style="width: 280px"
            @change="onStudyChange"
          >
            <el-option
              v-for="s in studies"
              :key="s.id"
              :label="`${s.code} · ${s.name}`"
              :value="s.id"
            />
          </el-select>
        </div>
      </div>

      <div class="perm-body">
        <div v-if="!selectedStudyId" class="perm-empty">
          <el-empty description="请先选择一个项目以配置权限" />
        </div>
        <template v-else>
          <el-tabs v-model="projectSubTab" class="project-sub-tabs">
            <el-tab-pane label="角色权限" name="api">
              <div class="sub-tab-toolbar">
                <div class="sub-tab-spacer" />
                <el-button @click="templateDrawerVisible = true">
                  <el-icon><Files /></el-icon>
                  模板管理
                </el-button>
                <el-button type="primary" :loading="saving" :disabled="!dirty" @click="save">
                  <el-icon><Check /></el-icon>
                  保存
                </el-button>
              </div>
              <PermissionTemplateSelector
                :study-id="selectedStudyId"
                :current-permissions="currentPermissionsForTemplate"
                :active-roles="activeRolesInStudy"
                @edit-role="openRoleEditor"
              />
              <el-divider />
              <ApiEndpointPermissions
                :project="selectedStudy"
                :matrix="apiMatrix"
                @update="onApiMatrixUpdate"
              />
            </el-tab-pane>
            <el-tab-pane label="成员管理" name="members">
              <div class="sub-tab-toolbar">
                <div class="sub-tab-spacer" />
                <el-button type="primary" @click="openAddMember">添加成员</el-button>
              </div>
              <el-table :data="memberRows" v-loading="membersLoading" stripe class="full-table">
                <el-table-column prop="full_name" label="姓名" min-width="140" />
                <el-table-column label="项目角色" min-width="140">
                  <template #default="{ row }">
                    <el-select
                      v-model="row.role_in_study"
                      size="small"
                      style="width: 130px"
                      @change="(val: string) => updateMemberRole(row.id, val)"
                      :disabled="!canEditMember(row) || !row.is_active || row.effectiveStatus === 'DISABLED_GLOBAL'"
                    >
                      <el-option v-for="(label, val) in activeRoleLabels" :key="val" :label="label" :value="val" />
                    </el-select>
                  </template>
                </el-table-column>
                <el-table-column label="状态" width="110">
                  <template #default="{ row }">
                    <el-tooltip v-if="row.effectiveStatus === 'DISABLED_GLOBAL'" content="请前往账号管理启用该账号" placement="top">
                      <el-tag type="danger">全局已禁用</el-tag>
                    </el-tooltip>
                    <el-tag v-else :type="row.is_active ? 'success' : 'danger'">
                      {{ row.is_active ? "启用" : "已禁用" }}
                    </el-tag>
                  </template>
                </el-table-column>
                <el-table-column prop="added_at" label="加入时间" min-width="160">
                  <template #default="{ row }">{{ displayDateTime(row.added_at) }}</template>
                </el-table-column>
                <el-table-column label="操作" width="160" align="center">
                  <template #default="{ row }">
                    <el-button
                      link
                      :type="row.is_active ? 'warning' : 'primary'"
                      size="small"
                      :disabled="!canEditMember(row) || row.effectiveStatus === 'DISABLED_GLOBAL'"
                      @click="toggleMemberActive(row)"
                    >
                      {{ row.is_active ? "停用" : "启用" }}
                    </el-button>
                    <el-button link type="danger" size="small" :disabled="!canEditMember(row)" @click="deleteMember(row)">
                      移除
                    </el-button>
                  </template>
                </el-table-column>
              </el-table>
            </el-tab-pane>
          </el-tabs>
        </template>
      </div>
    </template>

    <!-- ══════════════════════════════════════
         系统级权限
    ══════════════════════════════════════ -->
    <template v-else-if="activeTab === 'system'">
      <div class="perm-header">
        <div class="perm-header-left">
          <h2 class="perm-title">系统级权限</h2>
          <span class="perm-subtitle">只读展示，所有系统管理操作仅限 ADMIN 角色执行</span>
        </div>
      </div>
      <div class="perm-body">
        <div v-if="systemLoading" class="perm-empty">
          <el-skeleton :rows="8" animated />
        </div>
        <div v-else-if="!systemPermissions.length" class="perm-empty">
          <el-empty description="暂无系统级权限数据" />
        </div>
        <template v-else>
          <div v-for="(items, moduleKey) in systemPermissionsByModule" :key="moduleKey" class="system-module-block">
            <div class="system-module-header">
              <span class="system-module-title">{{ systemModuleLabels[moduleKey] || moduleKey }}</span>
              <el-tag size="small" type="info" round>{{ items.length }} 项操作</el-tag>
            </div>
            <el-table :data="items" border size="small" class="system-perm-table">
              <el-table-column prop="description" label="操作描述" min-width="180" />
              <el-table-column prop="permission_key" label="权限标识" min-width="220">
                <template #default="{ row }">
                  <code class="perm-key">{{ row.permission_key }}</code>
                </template>
              </el-table-column>
              <el-table-column prop="action" label="操作类型" width="100">
                <template #default="{ row }">
                  <el-tag :type="opTagType({ operation_key: row.permission_key, action: row.action })" size="small">
                    {{ opActionLabel({ operation_key: row.permission_key, action: row.action }) }}
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column label="授权角色" width="120">
                <template #default="{ row }">
                  <el-tag v-for="r in row.roles" :key="r" size="small" type="danger" style="margin-right: 4px">{{ r }}</el-tag>
                </template>
              </el-table-column>
            </el-table>
          </div>
        </template>
      </div>
    </template>

    <!-- ══════════════════════════════════════
         权限监控
    ══════════════════════════════════════ -->
    <template v-else-if="activeTab === 'monitoring'">
      <div class="perm-header">
        <div class="perm-header-left">
          <h2 class="perm-title">权限监控</h2>
          <span class="perm-subtitle">实时监控权限使用情况与异常告警</span>
        </div>
        <div class="perm-header-actions">
          <el-button @click="loadMonitoringData" :loading="monitoringLoading">
            <el-icon><RefreshRight /></el-icon>
            刷新
          </el-button>
          <el-button @click="doResetMetrics" :loading="resetting">重置指标</el-button>
        </div>
      </div>
      <div class="perm-body">
        <div class="perm-body-padded">
          <PermissionMonitoring
            :metrics="metrics"
            :health="health"
            :alerts="alerts"
            @refresh="loadMonitoringData"
          />
        </div>
      </div>
    </template>


    <!-- ══════════════════════════════════════
         模板管理抽屉
    ══════════════════════════════════════ -->
    <el-drawer v-model="templateDrawerVisible" title="权限模板管理" size="720px" direction="rtl" @open="onTemplateDrawerOpen">
      <el-tabs v-model="templateDrawerTab" class="drawer-tabs">

        <!-- 标签页：模板列表 -->
        <el-tab-pane label="模板列表" name="list">
          <div class="drawer-toolbar">
            <el-select v-model="typeFilter" placeholder="模板类型" clearable style="width: 140px" @change="loadTemplates">
              <el-option label="角色模板" value="ROLE" />
              <el-option label="场景模板" value="SCENARIO" />
              <el-option label="自定义模板" value="CUSTOM" />
            </el-select>
            <div class="filter-spacer" />
            <el-button type="primary" @click="openCreateTemplate">新增模板</el-button>
          </div>
          <el-table :data="templates" v-loading="templatesLoading" stripe style="margin-top: 12px">
            <el-table-column prop="name" label="模板名称" min-width="140">
              <template #default="{ row }">
                <span class="template-name">{{ row.name }}</span>
              </template>
            </el-table-column>
            <el-table-column prop="description" label="描述" min-width="160" show-overflow-tooltip />
            <el-table-column prop="template_type" label="类型" width="100">
              <template #default="{ row }">
                <el-tag :type="typeTagType(row.template_type)" size="small">{{ typeLabel(row.template_type) }}</el-tag>
              </template>
            </el-table-column>
            <el-table-column label="权限数" width="80">
              <template #default="{ row }">{{ countPermissions(row) }}</template>
            </el-table-column>
            <el-table-column label="操作" width="120" fixed="right">
              <template #default="{ row }">
                <el-button link type="primary" @click="openEditTemplate(row)">编辑</el-button>
                <el-button link type="danger" :disabled="row.is_system" @click="confirmDeleteTemplate(row)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>

        <!-- 标签页：生效管理 -->
        <el-tab-pane label="生效管理" name="active" :disabled="!selectedStudyId">
          <div class="active-roles-desc">
            <el-alert
              title="生效的角色将映射到成员管理的项目角色中，未生效的角色不可在成员管理中分配。"
              type="info"
              :closable="false"
              show-icon
              style="margin-bottom: 16px"
            />
          </div>
          <div class="active-roles-list" v-loading="activeRolesLoading">
            <div v-for="role in ALL_ROLES" :key="role.key" class="active-role-row">
              <div class="active-role-info">
                <span class="active-role-icon">{{ role.icon }}</span>
                <div>
                  <div class="active-role-name">{{ role.label }}</div>
                  <div class="active-role-desc">{{ role.desc }}</div>
                </div>
              </div>
              <el-switch
                :model-value="activeRolesDraft.includes(role.key)"
                @change="(v: boolean) => toggleActiveRole(role.key, v)"
              />
            </div>
          </div>
          <div class="drawer-footer">
            <el-button type="primary" :loading="activeRolesSaving" @click="saveActiveRoles">保存</el-button>
          </div>
        </el-tab-pane>

        <!-- 标签页：编辑权限 -->
        <el-tab-pane label="编辑权限" name="edit-role" :disabled="!selectedStudyId">
          <div class="role-editor-layout" v-loading="roleEditorLoading">
            <!-- 左侧角色列表 -->
            <div class="role-editor-sidebar">
              <div
                v-for="role in ALL_ROLES"
                :key="role.key"
                class="role-sidebar-item"
                :class="{ active: editingRole === role.key }"
                @click="selectRoleForEdit(role.key)"
              >
                <span class="role-sidebar-icon">{{ role.icon }}</span>
                <div class="role-sidebar-info">
                  <div class="role-sidebar-name">{{ role.label }}</div>
                  <div class="role-sidebar-count" v-if="editingRole === role.key && Object.keys(roleEditorDraft).length">
                    {{ Object.values(roleEditorDraft).filter(Boolean).length }} 项已启用
                  </div>
                </div>
                <el-icon v-if="editingRole === role.key" class="role-sidebar-arrow"><ArrowRight /></el-icon>
              </div>
            </div>

            <!-- 右侧权限编辑区 -->
            <div class="role-editor-content">
              <template v-if="editingRole">
                <div class="role-editor-toolbar">
                  <el-input v-model="roleEditorSearch" placeholder="搜索权限..." clearable style="width: 220px">
                    <template #prefix><el-icon><Search /></el-icon></template>
                  </el-input>
                  <div class="filter-spacer" />
                  <el-button size="small" @click="roleEditorSelectAll(true)">全选</el-button>
                  <el-button size="small" @click="roleEditorSelectAll(false)">全不选</el-button>
                </div>
                <div class="role-editor-modules">
                  <div v-for="(ops, mod) in roleEditorGrouped" :key="mod" class="role-editor-module">
                    <div class="role-editor-module-header">
                      <span>{{ roleEditorModuleLabel(mod) }}</span>
                      <el-tag size="small" type="info">{{ ops.length }}</el-tag>
                    </div>
                    <div class="role-editor-ops">
                      <div v-for="op in ops" :key="op.operation_key" class="role-editor-op-row">
                        <el-checkbox
                          :model-value="roleEditorDraft[op.operation_key] ?? false"
                          @change="(v: boolean) => roleEditorDraft[op.operation_key] = v"
                        />
                        <el-tag :type="opTagType(op)" size="small" class="op-action-tag">{{ opActionLabel(op) }}</el-tag>
                        <span class="op-desc">{{ op.description || op.operation_key }}</span>
                      </div>
                    </div>
                  </div>
                </div>
                <div class="drawer-footer">
                  <el-button type="primary" :loading="roleEditorSaving" @click="saveRoleEditor">
                    保存 {{ ROLE_LABELS[editingRole] }} 权限
                  </el-button>
                </div>
              </template>
              <el-empty v-else description="请从左侧选择角色" style="padding: 80px 0" />
            </div>
          </div>
        </el-tab-pane>

      </el-tabs>
    </el-drawer>

    <!-- 新增/编辑模板对话框 -->
    <el-dialog v-model="templateDialogVisible" :title="editingTemplateId ? '编辑权限模板' : '新增权限模板'" width="520px" @close="resetTemplateForm">
      <el-form :model="templateForm" :rules="templateRules" ref="templateFormRef" label-width="90px">
        <el-form-item label="模板名称" prop="name">
          <el-input v-model="templateForm.name" placeholder="请输入模板名称" />
        </el-form-item>
        <el-form-item label="描述">
          <el-input v-model="templateForm.description" type="textarea" :rows="2" placeholder="可选描述" />
        </el-form-item>
        <el-form-item label="模板类型" prop="template_type">
          <el-select v-model="templateForm.template_type" style="width: 100%">
            <el-option label="角色模板" value="ROLE" />
            <el-option label="场景模板" value="SCENARIO" />
            <el-option label="自定义模板" value="CUSTOM" />
          </el-select>
        </el-form-item>
        <el-form-item label="分类">
          <el-input v-model="templateForm.category" placeholder="如 PM / CRA / PV" />
        </el-form-item>
        <el-form-item label="推荐角色">
          <el-input v-model="templateForm.recommended_roles" placeholder="如 PM,CRA" />
        </el-form-item>
        <el-form-item label="标签">
          <el-input v-model="templateForm.tags" placeholder="可选标签" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="templateDialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="templateSaving" @click="submitTemplateForm">保存</el-button>
      </template>
    </el-dialog>

    <!-- 新增成员对话框 -->
    <el-dialog v-model="addMemberVisible" title="新增成员" width="480px" @close="resetAddMemberForm">
      <el-form :model="addMemberForm" :rules="addMemberRules" ref="addMemberFormRef" label-width="90px">
        <el-form-item label="用户" prop="user_id">
          <el-select v-model="addMemberForm.user_id" filterable placeholder="请选择用户" style="width: 100%">
            <el-option
              v-for="u in availableCandidates"
              :key="u.id"
              :label="u.full_name"
              :value="u.id"
              :disabled="!u.is_active"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="项目角色" prop="role_in_study">
          <el-select v-model="addMemberForm.role_in_study" style="width: 100%">
            <el-option v-for="(label, val) in activeRoleLabels" :key="val" :label="label" :value="val" />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="addMemberVisible = false">取消</el-button>
        <el-button type="primary" :loading="addMemberSaving" @click="submitAddMember">添加</el-button>
      </template>
    </el-dialog>

    <!-- 角色权限编辑抽屉已合并至模板管理抽屉 -->
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, watch, reactive } from "vue";
import { useRoute, useRouter } from "vue-router";
import { ElMessage, ElMessageBox } from "element-plus";
import { RefreshRight, Check, Files, Search, ArrowRight } from "@element-plus/icons-vue";
import type { FormInstance, FormRules } from "element-plus";
import type {
  ApiEndpointPermissionsResponse,
  PermissionMetricsResponse,
  AlertsResponse,
  HealthResponse,
  Study,
  StudyMember,
  UserInfo,
} from "@/types/api";
import {
  fetchApiEndpointPermissions,
  updateApiEndpointPermissions,
  fetchApiOperations,
  fetchPermissionMetrics,
  fetchPermissionAlerts,
  fetchPermissionHealth,
  resetPermissionMetrics,
  fetchPermissionTemplates,
  createPermissionTemplate,
  updatePermissionTemplate,
  deletePermissionTemplate,
  fetchSystemPermissions,
  fetchActiveRoles,
  updateActiveRoles,
  type PermissionTemplate,
  type SystemPermissionItem,
} from "@/api/projectPermissions";
import { addMember, listMemberCandidates, listMembers, removeMember, updateMember } from "@/api/members";
import { fetchStudies } from "@/api/studies";
import { useAuthStore } from "@/store/auth";
import { displayDateTime } from "@/utils/display";
import ApiEndpointPermissions from "@/components/ApiEndpointPermissions.vue";
import PermissionMonitoring from "@/components/PermissionMonitoring.vue";
import PermissionTemplateSelector from "@/components/PermissionTemplateSelector.vue";

const route = useRoute();
const router = useRouter();
const auth = useAuthStore();

const ROLE_LABELS: Record<string, string> = {
  PM: "项目负责人", CRA: "CRA", PV: "PV",
  MEDICAL_REVIEW: "医学审核", IMP: "药品管理员", QA: "QA",
};

const activeRoleLabels = computed(() => {
  const result: Record<string, string> = {};
  for (const role of activeRolesInStudy.value) {
    if (ROLE_LABELS[role]) result[role] = ROLE_LABELS[role];
  }
  return result;
});
const ROLE_RANK: Record<string, number> = {
  ADMIN: 100, PM: 80, QA: 60, PV: 50, MEDICAL_REVIEW: 50, CRA: 40, IMP: 40,
};

// ── 顶层标签 ──
const tabFromPath = (): "project" | "system" | "monitoring" => {
  const p = route.path;
  if (p.endsWith("/system")) return "system";
  if (p.endsWith("/monitoring")) return "monitoring";
  return "project";
};
const activeTab = computed({
  get: () => tabFromPath(),
  set: (tab: "project" | "system" | "monitoring") => {
    const pathMap = { system: "/admin/permissions/system", project: "/admin/permissions/project", monitoring: "/admin/permissions/monitoring" };
    router.push({ path: pathMap[tab], query: route.query });
  },
});
const pageLoading = ref(false);

// ═══════════════════════════════════════════
// 项目权限配置
// ═══════════════════════════════════════════
const studies = ref<Study[]>([]);
const selectedStudyId = ref<string>("");
const selectedStudy = computed(() => studies.value.find((s) => s.id === selectedStudyId.value) ?? null);
const projectSubTab = ref<"api" | "members">("api");

// 接口级权限
const apiMatrix = ref<ApiEndpointPermissionsResponse | null>(null);
const dirty = ref(false);
const saving = ref(false);

const currentPermissionsForTemplate = computed(() => {
  if (!apiMatrix.value) return undefined;
  const result: Record<string, Record<string, boolean>> = {};
  for (const [role, endpoints] of Object.entries(apiMatrix.value as Record<string, Record<string, { allowed: boolean }>>)) {
    result[role] = {};
    for (const [key, val] of Object.entries(endpoints)) result[role][key] = val.allowed;
  }
  return result;
});

const loadStudies = async () => {
  try {
    const res = await fetchStudies();
    studies.value = res.data.items ?? [];
  } catch {
    ElMessage.error("加载项目列表失败");
  }
};

const loadPermissionData = async () => {
  if (!selectedStudyId.value) return;
  pageLoading.value = true;
  try {
    const res = await fetchApiEndpointPermissions(selectedStudyId.value);
    apiMatrix.value = res.data;
    dirty.value = false;
  } catch {
    ElMessage.error("加载权限数据失败");
  } finally {
    pageLoading.value = false;
  }
};

const onStudyChange = async (id: string) => {
  apiMatrix.value = null;
  dirty.value = false;
  members.value = [];
  candidates.value = [];
  activeRolesDraft.value = [];
  router.replace({ query: { ...route.query, projectId: id } });
  await Promise.all([loadPermissionData(), loadMembers(), loadActiveRoles()]);
  loadCandidates();
};

const onApiMatrixUpdate = (m: ApiEndpointPermissionsResponse) => { apiMatrix.value = m; dirty.value = true; };

const activeRolesInStudy = computed(() => activeRolesDraft.value);

// 把 apiMatrix（可能混有 { allowed: boolean } 或 boolean）展平为 boolean 格式
const flattenMatrix = (matrix: ApiEndpointPermissionsResponse): Record<string, Record<string, boolean>> => {
  const result: Record<string, Record<string, boolean>> = {};
  for (const [role, endpoints] of Object.entries(matrix as Record<string, Record<string, any>>)) {
    result[role] = {};
    for (const [key, val] of Object.entries(endpoints)) {
      result[role][key] = typeof val === "boolean" ? val : val.allowed;
    }
  }
  return result;
};

const save = async () => {
  if (!selectedStudyId.value || !dirty.value || !apiMatrix.value) return;
  saving.value = true;
  try {
    const res = await updateApiEndpointPermissions(selectedStudyId.value, flattenMatrix(apiMatrix.value));
    apiMatrix.value = res.data;
    dirty.value = false;
    ElMessage.success("权限已保存");
  } catch {
    ElMessage.error("保存权限失败");
  } finally {
    saving.value = false;
  }
};

// 成员管理
const members = ref<StudyMember[]>([]);
const candidates = ref<UserInfo[]>([]);
const membersLoading = ref(false);
const addMemberVisible = ref(false);
const addMemberSaving = ref(false);
const addMemberFormRef = ref<FormInstance>();
const addMemberForm = reactive({ user_id: "", role_in_study: "PM" });
const addMemberRules: FormRules = {
  user_id: [{ required: true, message: "请选择用户", trigger: "change" }],
  role_in_study: [{ required: true, message: "请选择角色", trigger: "change" }],
};

const canEditMember = (row: { user_id: string; role_in_study: string; user?: any }) => {
  if (auth.user?.role !== "ADMIN") return false;
  if (row.user_id === auth.user?.id) return false;
  if (row.user?.role === "ADMIN") return false;
  return true;
};

const memberRows = computed(() =>
  members.value.map((m) => {
    const user = candidates.value.find((u) => u.id === m.user_id) || m.user;
    const effectiveStatus = user && (user as any).is_active === false ? "DISABLED_GLOBAL" : m.is_active ? "ACTIVE" : "DISABLED";
    return { ...m, full_name: (user as any)?.full_name || m.user_id, effectiveStatus };
  })
);

const availableCandidates = computed(() => {
  const ids = new Set(members.value.map((m) => m.user_id));
  return candidates.value.filter((u) => !ids.has(u.id));
});

const loadMembers = async () => {
  if (!selectedStudyId.value) return;
  membersLoading.value = true;
  try {
    const { data } = await listMembers(selectedStudyId.value, { limit: 500, include_inactive: true });
    members.value = Array.isArray(data) ? data : (data as any).items ?? [];
  } catch {
    ElMessage.error("加载成员失败");
  } finally {
    membersLoading.value = false;
  }
};

const loadCandidates = async () => {
  if (!selectedStudyId.value) return;
  try {
    const { data } = await listMemberCandidates(selectedStudyId.value, { limit: 500 });
    candidates.value = data ?? [];
  } catch {
    candidates.value = [];
  }
};

const openAddMember = () => {
  addMemberForm.user_id = "";
  addMemberForm.role_in_study = "PM";
  addMemberVisible.value = true;
};

const resetAddMemberForm = () => { addMemberFormRef.value?.clearValidate(); };

const submitAddMember = async () => {
  const valid = await addMemberFormRef.value?.validate().catch(() => false);
  if (!valid) return;
  addMemberSaving.value = true;
  try {
    await addMember(selectedStudyId.value, addMemberForm);
    ElMessage.success("成员已添加");
    addMemberVisible.value = false;
    await Promise.all([loadMembers(), loadCandidates()]);
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || "添加失败");
  } finally {
    addMemberSaving.value = false;
  }
};

const updateMemberRole = async (memberId: string, role: string) => {
  try {
    await updateMember(selectedStudyId.value, memberId, { role_in_study: role });
    ElMessage.success("角色已更新");
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || "更新失败");
    loadMembers();
  }
};

const toggleMemberActive = async (row: any) => {
  if (row.is_active) {
    const ok = await ElMessageBox.confirm("确认停用该成员？", "停用成员", { type: "warning" }).catch(() => null);
    if (!ok) return;
  }
  try {
    await updateMember(selectedStudyId.value, row.id, { is_active: !row.is_active });
    ElMessage.success(row.is_active ? "已停用" : "已启用");
    loadMembers();
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || "操作失败");
  }
};

const deleteMember = async (row: any) => {
  const ok = await ElMessageBox.confirm("确认将该账号从本项目移除？账号本身不会被删除。", "移除成员", {
    type: "warning",
  }).catch(() => null);
  if (!ok) return;
  try {
    await removeMember(selectedStudyId.value, row.id);
    ElMessage.success("已移除");
    await Promise.all([loadMembers(), loadCandidates()]);
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || "移除失败");
  }
};

// ═══════════════════════════════════════════
// 模板管理（抽屉）
// ═══════════════════════════════════════════
const templateDrawerVisible = ref(false);
const templateDrawerTab = ref<"list" | "active" | "edit-role">("list");
const templates = ref<PermissionTemplate[]>([]);
const templatesLoading = ref(false);
const typeFilter = ref<string | undefined>(undefined);
const templateDialogVisible = ref(false);
const editingTemplateId = ref<string | null>(null);
const templateFormRef = ref<FormInstance>();
const templateSaving = ref(false);

const ALL_ROLES = [
  { key: "PM", label: "项目负责人", icon: "👑", desc: "项目管理员，拥有所有权限" },
  { key: "CRA", label: "CRA", icon: "📋", desc: "数据输入和日常管理人员" },
  { key: "PV", label: "PV", icon: "🔍", desc: "访视和参与者管理人员" },
  { key: "MEDICAL_REVIEW", label: "医学审核", icon: "🏥", desc: "医学审核人员" },
  { key: "IMP", label: "药品管理员", icon: "📦", desc: "物资和设备管理人员" },
  { key: "QA", label: "QA", icon: "✅", desc: "质量检查和审计人员" },
];

const activeRolesDraft = ref<string[]>([]);
const activeRolesLoading = ref(false);
const activeRolesSaving = ref(false);

const onTemplateDrawerOpen = async () => {
  await loadTemplates();
  if (selectedStudyId.value) {
    await Promise.all([loadActiveRoles(), ensureOperationsLoaded()]);
  }
};

const loadActiveRoles = async () => {
  activeRolesLoading.value = true;
  try {
    const res = await fetchActiveRoles(selectedStudyId.value);
    activeRolesDraft.value = res.data.active_roles;
  } catch {
    ElMessage.error("加载生效角色失败");
  } finally {
    activeRolesLoading.value = false;
  }
};

const toggleActiveRole = (role: string, active: boolean) => {
  if (active) {
    if (!activeRolesDraft.value.includes(role)) activeRolesDraft.value.push(role);
  } else {
    activeRolesDraft.value = activeRolesDraft.value.filter((r) => r !== role);
  }
};

const saveActiveRoles = async () => {
  activeRolesSaving.value = true;
  try {
    await updateActiveRoles(selectedStudyId.value, activeRolesDraft.value);
    ElMessage.success("生效角色已保存");
  } catch {
    ElMessage.error("保存失败");
  } finally {
    activeRolesSaving.value = false;
  }
};

const templateForm = ref({
  name: "", description: "", template_type: "CUSTOM" as "ROLE" | "SCENARIO" | "CUSTOM",
  category: "", recommended_roles: "", tags: "",
});
const templateRules: FormRules = {
  name: [{ required: true, message: "请输入模板名称", trigger: "blur" }],
  template_type: [{ required: true, message: "请选择模板类型", trigger: "change" }],
};

const typeLabel = (t: string) => ({ ROLE: "角色模板", SCENARIO: "场景模板", CUSTOM: "自定义" }[t] ?? t);
const typeTagType = (t: string) =>
  ({ ROLE: "primary", SCENARIO: "warning", CUSTOM: "success" } as Record<string, any>)[t] ?? "info";
const countPermissions = (row: PermissionTemplate) => {
  let n = 0;
  for (const perms of Object.values(row.permissions) as Record<string, boolean>[])
    n += Object.values(perms).filter(Boolean).length;
  return n;
};

const loadTemplates = async () => {
  templatesLoading.value = true;
  try {
    const res = await fetchPermissionTemplates(typeFilter.value ? { template_type: typeFilter.value } : undefined);
    templates.value = res.data;
  } catch {
    ElMessage.error("加载模板失败");
  } finally {
    templatesLoading.value = false;
  }
};

const openCreateTemplate = () => {
  editingTemplateId.value = null;
  resetTemplateForm();
  templateDialogVisible.value = true;
};

const openEditTemplate = (row: PermissionTemplate) => {
  editingTemplateId.value = row.id;
  templateForm.value = {
    name: row.name, description: row.description ?? "",
    template_type: row.template_type, category: row.category ?? "",
    recommended_roles: row.recommended_roles ?? "", tags: row.tags ?? "",
  };
  templateDialogVisible.value = true;
};

const resetTemplateForm = () => {
  templateForm.value = { name: "", description: "", template_type: "CUSTOM", category: "", recommended_roles: "", tags: "" };
  templateFormRef.value?.clearValidate();
};

const submitTemplateForm = async () => {
  const valid = await templateFormRef.value?.validate().catch(() => false);
  if (!valid) return;
  templateSaving.value = true;
  try {
    const payload = {
      ...templateForm.value,
      description: templateForm.value.description || undefined,
      category: templateForm.value.category || undefined,
      recommended_roles: templateForm.value.recommended_roles || undefined,
      tags: templateForm.value.tags || undefined,
      permissions: editingTemplateId.value
        ? (templates.value.find((t) => t.id === editingTemplateId.value)?.permissions ?? {})
        : {},
    };
    if (editingTemplateId.value) {
      await updatePermissionTemplate(editingTemplateId.value, payload);
      ElMessage.success("模板已更新");
    } else {
      await createPermissionTemplate(payload);
      ElMessage.success("模板已创建");
    }
    templateDialogVisible.value = false;
    await loadTemplates();
  } catch {
    ElMessage.error("保存失败");
  } finally {
    templateSaving.value = false;
  }
};

const confirmDeleteTemplate = async (row: PermissionTemplate) => {
  await ElMessageBox.confirm(`确认删除模板「${row.name}」？此操作不可撤销。`, "删除确认", {
    type: "warning", confirmButtonText: "删除", confirmButtonClass: "el-button--danger",
  });
  try {
    await deletePermissionTemplate(row.id);
    ElMessage.success("已删除");
    await loadTemplates();
  } catch {
    ElMessage.error("删除失败");
  }
};

// ═══════════════════════════════════════════
// 系统级权限
// ═══════════════════════════════════════════
const systemPermissions = ref<SystemPermissionItem[]>([]);
const systemModuleLabels = ref<Record<string, string>>({});
const systemLoading = ref(false);

const systemPermissionsByModule = computed(() => {
  const map: Record<string, SystemPermissionItem[]> = {};
  for (const item of systemPermissions.value) {
    if (!map[item.module]) map[item.module] = [];
    map[item.module].push(item);
  }
  return map;
});

const loadSystemPermissions = async () => {
  systemLoading.value = true;
  try {
    const res = await fetchSystemPermissions();
    systemPermissions.value = res.data.permissions;
    systemModuleLabels.value = res.data.module_labels;
  } catch {
    ElMessage.error("加载系统级权限失败");
  } finally {
    systemLoading.value = false;
  }
};

// ═══════════════════════════════════════════
// 权限监控
// ═══════════════════════════════════════════
const metrics = ref<PermissionMetricsResponse | null>(null);
const health = ref<HealthResponse | null>(null);
const alerts = ref<AlertsResponse | null>(null);
const monitoringLoading = ref(false);
const resetting = ref(false);

const loadMonitoringData = async () => {
  monitoringLoading.value = true;
  try {
    const [metricsRes, healthRes, alertsRes] = await Promise.all([
      fetchPermissionMetrics(),
      fetchPermissionHealth(),
      fetchPermissionAlerts(undefined, 20),
    ]);
    metrics.value = metricsRes.data;
    health.value = healthRes.data;
    alerts.value = alertsRes.data;
  } catch {
    ElMessage.error("加载监控数据失败");
  } finally {
    monitoringLoading.value = false;
  }
};

const doResetMetrics = async () => {
  resetting.value = true;
  try {
    await resetPermissionMetrics();
    await loadMonitoringData();
    ElMessage.success("指标已重置");
  } catch {
    ElMessage.error("重置失败");
  } finally {
    resetting.value = false;
  }
};

// ═══════════════════════════════════════════
// 角色权限编辑器（抽屉）
// ═══════════════════════════════════════════
interface RoleEditorOp {
  operation_key: string;
  module: string;
  action: string;
  description: string;
}

const editingRole = ref("");
const roleEditorSearch = ref("");
const roleEditorDraft = ref<Record<string, boolean>>({});
const roleEditorSaving = ref(false);
const roleEditorLoading = ref(false);
const allOperations = ref<RoleEditorOp[]>([]);

const ROLE_EDITOR_MODULE_LABELS: Record<string, string> = {
  subjects: "参与者管理", sites: "中心管理", risk_issues: "风险问题",
  monitoring_audit: "监查稽查", project_members: "项目成员",
  project_milestones: "项目里程碑", project_overview: "项目总览",
  fees: "合同费用", materials: "物资管理", material_equipments: "物资设备",
  documents: "文件版本", startup_ethics: "立项与伦理", startup_auth: "启动与授权",
  audit_export: "审计日志", faq: "FAQ", shared_library: "共享库",
  attachments: "附件管理", dashboard: "仪表板", subject_histories: "参与者历史",
};

const roleEditorModuleLabel = (mod: string) => ROLE_EDITOR_MODULE_LABELS[mod] || mod;

const getOpVerb = (op: { operation_key: string; action: string }): string => {
  const suffix = op.operation_key.split(":").pop() || "";
  if (suffix === "create") return "create";
  if (suffix === "read" || suffix === "list") return "read";
  if (suffix === "update") return "update";
  if (suffix === "delete") return "delete";
  if (suffix === "export") return "export";
  return op.action;
};

const opActionLabel = (op: { operation_key: string; action: string }) => {
  const verb = getOpVerb(op);
  return ({ create: "创建", read: "读取", update: "更新", delete: "删除", export: "导出", write: "写入" }[verb] ?? verb);
};

const opTagType = (op: { operation_key: string; action: string }) => {
  const verb = getOpVerb(op);
  return (({ create: "success", read: "info", update: "warning", delete: "danger", export: "", write: "success" } as Record<string, string>)[verb] ?? "info");
};

const roleEditorGrouped = computed(() => {
  const search = roleEditorSearch.value.toLowerCase();
  const filtered = allOperations.value.filter((op) =>
    !search ||
    op.description.toLowerCase().includes(search) ||
    op.operation_key.toLowerCase().includes(search) ||
    roleEditorModuleLabel(op.module).includes(search)
  );
  const map: Record<string, RoleEditorOp[]> = {};
  for (const op of filtered) {
    if (!map[op.module]) map[op.module] = [];
    map[op.module].push(op);
  }
  return map;
});

const selectRoleForEdit = (role: string) => {
  editingRole.value = role;
  roleEditorSearch.value = "";
  initRoleEditor();
};

const openRoleEditor = async (role: string) => {
  templateDrawerTab.value = "edit-role";
  templateDrawerVisible.value = true;
  await ensureOperationsLoaded();
  selectRoleForEdit(role);
};

const ensureOperationsLoaded = async () => {
  if (allOperations.value.length) return;
  roleEditorLoading.value = true;
  try {
    const res = await fetchApiOperations();
    allOperations.value = res.data.operations;
  } catch {
    ElMessage.error("加载权限操作失败");
  } finally {
    roleEditorLoading.value = false;
  }
};

const initRoleEditor = () => {
  const role = editingRole.value;
  const draft: Record<string, boolean> = {};
  if (apiMatrix.value && apiMatrix.value[role]) {
    for (const [key, val] of Object.entries(apiMatrix.value[role] as Record<string, any>)) {
      draft[key] = typeof val === "boolean" ? val : val.allowed;
    }
  }
  roleEditorDraft.value = draft;
};

const roleEditorSelectAll = (val: boolean) => {
  const ops = Object.values(roleEditorGrouped.value).flat();
  for (const op of ops) roleEditorDraft.value[op.operation_key] = val;
};

const saveRoleEditor = async () => {
  if (!selectedStudyId.value || !apiMatrix.value) return;
  roleEditorSaving.value = true;
  try {
    const payload = flattenMatrix(apiMatrix.value);
    if (!payload[editingRole.value]) payload[editingRole.value] = {};
    for (const [key, val] of Object.entries(roleEditorDraft.value)) {
      payload[editingRole.value][key] = val;
    }
    const res = await updateApiEndpointPermissions(selectedStudyId.value, payload);
    apiMatrix.value = res.data;
    dirty.value = false;
    const savedRole = editingRole.value;
    editingRole.value = "";
    ElMessage.success(`${ROLE_LABELS[savedRole] || savedRole} 权限已保存`);
  } catch {
    ElMessage.error("保存失败");
  } finally {
    roleEditorSaving.value = false;
  }
};

// ═══════════════════════════════════════════
// 懒加载 & 初始化
// ═══════════════════════════════════════════
watch(() => route.path, (path) => {
  if (path.endsWith("/system") && !systemPermissions.value.length) loadSystemPermissions();
  if (path.endsWith("/monitoring") && !metrics.value) loadMonitoringData();
});

onMounted(async () => {
  await loadStudies();
  await loadTemplates();

  const qProjectId = route.query.projectId as string | undefined;
  const qSub = route.query.sub as string | undefined;
  if (qProjectId) {
    selectedStudyId.value = qProjectId;
    if (qSub === "members") projectSubTab.value = "members";
    await Promise.all([loadPermissionData(), loadMembers(), loadActiveRoles()]);
    loadCandidates();
  }

  const tab = tabFromPath();
  if (tab === "system" && !systemPermissions.value.length) loadSystemPermissions();
  if (tab === "monitoring" && !metrics.value) loadMonitoringData();
});
</script>

<style scoped>
/* ── 页面容器：铺满，无 padding ── */
.perm-page {
  display: flex;
  flex-direction: column;
  margin: -6px -8px;
  min-height: calc(100vh - 52px);
  min-height: calc(100dvh - 52px);
  background: #f5f7fa;
}

/* ── 顶部标题栏 ── */
.perm-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 28px 16px;
  background: #fff;
  border-bottom: 1px solid #e8edf3;
  flex-shrink: 0;
  gap: 16px;
}

.perm-header-left {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.perm-title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: #1a1f2e;
  line-height: 1.3;
}

.perm-subtitle {
  font-size: 13px;
  color: #8c96a8;
}

.perm-header-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}

/* ── 内容区：可滚动 ── */
.perm-body {
  flex: 1;
  overflow-y: auto;
  padding: 20px 0 20px;
}

.perm-empty {
  padding: 80px 28px;
  display: flex;
  justify-content: center;
}

.perm-body-padded {
  padding: 0 28px;
}

/* ── 项目权限：子 tabs ── */
.project-sub-tabs {
  background: #fff;
  border-radius: 0;
  padding: 0 28px 24px;
}

:deep(.project-sub-tabs .el-tabs__header) {
  margin-bottom: 16px;
}

.sub-tab-toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 16px;
}

.sub-tab-spacer { flex: 1; }

.full-table { width: 100%; }

/* ── 系统级权限：模块块 ── */
.system-module-block {
  background: #fff;
  border-radius: 0;
  padding: 20px 28px;
  margin-bottom: 12px;
  border-bottom: 1px solid #eef0f4;
}

.system-module-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
}

.system-module-title {
  font-size: 15px;
  font-weight: 600;
  color: #1a1f2e;
}

.system-perm-table { width: 100%; }

.perm-key {
  font-family: 'SF Mono', 'Fira Code', monospace;
  font-size: 12px;
  background: #f0f4f8;
  padding: 2px 8px;
  border-radius: 4px;
  color: #4a5568;
}

/* ── 抽屉内部 ── */
.filter-spacer { flex: 1; }

.drawer-toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 4px;
}

.drawer-tabs { padding-top: 4px; }

.drawer-footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding-top: 16px;
  margin-top: 16px;
  border-top: 1px solid #edf2f8;
}

/* ── 生效角色列表 ── */
.active-roles-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.active-role-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  border-radius: 6px;
  border: 1px solid #edf2f8;
  background: #fff;
}

.active-role-row:hover { background: #f5f7fa; }

.active-role-info {
  display: flex;
  align-items: center;
  gap: 12px;
}

.active-role-icon { font-size: 20px; }

.active-role-name {
  font-size: 14px;
  font-weight: 600;
  color: #303133;
}

.active-role-desc {
  font-size: 12px;
  color: #909399;
  margin-top: 2px;
}

.template-name { font-weight: 500; }

/* ── 角色编辑器 ── */
.role-editor-layout {
  display: flex;
  height: calc(100vh - 200px);
  gap: 0;
}

.role-editor-sidebar {
  width: 160px;
  flex-shrink: 0;
  border-right: 1px solid #edf2f8;
  overflow-y: auto;
  padding: 4px 0;
}

.role-sidebar-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  cursor: pointer;
  border-radius: 6px;
  margin: 2px 4px;
  transition: background 0.15s;
}

.role-sidebar-item:hover { background: #f5f7fa; }

.role-sidebar-item.active {
  background: #ecf5ff;
  color: #409eff;
}

.role-sidebar-icon { font-size: 18px; flex-shrink: 0; }

.role-sidebar-info { flex: 1; min-width: 0; }

.role-sidebar-name {
  font-size: 13px;
  font-weight: 500;
  color: #303133;
}

.role-sidebar-item.active .role-sidebar-name { color: #409eff; }

.role-sidebar-count {
  font-size: 11px;
  color: #67c23a;
  margin-top: 2px;
}

.role-sidebar-arrow {
  font-size: 12px;
  color: #409eff;
  flex-shrink: 0;
}

.role-editor-content {
  flex: 1;
  overflow-y: auto;
  padding: 0 16px;
  display: flex;
  flex-direction: column;
}

.role-editor-modules { flex: 1; }

.role-editor-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 16px;
}

.role-editor-module { margin-bottom: 20px; }

.role-editor-module-header {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 600;
  color: #303133;
  margin-bottom: 8px;
  padding-bottom: 6px;
  border-bottom: 1px solid #edf2f8;
}

.role-editor-ops {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.role-editor-op-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 0;
}

.op-action-tag {
  flex-shrink: 0;
  width: 42px;
  text-align: center;
}

.op-desc {
  font-size: 13px;
  color: #303133;
}
</style>
