<script setup lang="tsx">
import { ref, computed, nextTick } from "vue";
import { usePermission } from "./utils/hook";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import { usePublicHooks } from "@/views/system/hooks";
import { addDialog } from "@/components/ReDialog";
import { deviceDetection, delay, subBefore, useResizeObserver } from "@pureadmin/utils";
import PermissionDefineDialog from "./components/PermissionDefineDialog.vue";

import Refresh from "~icons/ep/refresh";
import Close from "~icons/ep/close";
import Check from "~icons/ep/check";
import Search from "~icons/ep/search";
import Unlock from "~icons/ep/unlock";
import Setting from "~icons/ep/setting";

defineOptions({
  name: "SystemPermission"
});

const {
  loading,
  saving,
  filteredRoles,
  selectedRole,
  roleSearch,
  filteredPermissionTree,
  checkedIds,
  checkedCount,
  hasChanges,
  permissionSearch,
  expandedModules,

  selectRole,
  togglePermission,
  toggleModule,
  isModuleAllChecked,
  isModuleIndeterminate,
  handleSave,
  handleReset,
  refresh
} = usePermission();

const { switchStyle } = usePublicHooks();
const contentRef = ref();
const leftPanelRef = ref();
const rightPanelRef = ref();
const panelHeight = ref(500);

// 权限定义弹窗
function openPermissionDefine() {
  addDialog({
    title: "权限定义管理",
    width: "80%",
    draggable: true,
    closeOnClickModal: false,
    fullscreen: deviceDetection(),
    fullscreenIcon: true,
    contentRenderer: () => (
      <PermissionDefineDialog
        onSaved={() => refresh()}
      />
    )
  });
}

// 获取操作类型标签样式
function getOpTypeTag(opType: string) {
  const colorMap: Record<string, string> = {
    read: "primary",
    create: "success",
    update: "warning",
    delete: "danger",
    execute: "info",
    export: "",
    import: "",
    distribute: "success",
    review: "warning",
    generate: ""
  };
  const tagType = colorMap[opType] || "info";
  return { type: tagType as any, label: opType };
}

// 自适应高度
const iconClass = [
  "w-[22px]", "h-[22px]", "flex", "justify-center", "items-center",
  "outline-hidden", "rounded-[4px]", "cursor-pointer", "transition-colors",
  "hover:bg-[#0000000f]", "dark:hover:bg-[#ffffff1f]", "dark:hover:text-[#ffffffd9]"
];

// 切换模块展开/折叠
function toggleModuleExpand(moduleId: string | number) {
  const id = String(moduleId);
  const list = expandedModules.value;
  const idx = list.indexOf(id);
  if (idx >= 0) {
    list.splice(idx, 1);
  } else {
    list.push(id);
  }
}

useResizeObserver(contentRef, async () => {
  await nextTick();
  delay(60).then(() => {
    if (contentRef.value) {
      const rect = contentRef.value.getBoundingClientRect();
      if (rect.height > 0) {
        panelHeight.value = rect.height - 20;
      }
    }
  });
});
</script>

<template>
  <div class="main" ref="contentRef">
    <!-- 顶部操作栏 -->
    <div class="top-bar bg-bg_color px-6 py-3 flex items-center justify-between flex-wrap gap-3">
      <div class="flex items-center gap-3">
        <el-button
          type="primary"
          plain
          :icon="useRenderIcon(Setting)"
          @click="openPermissionDefine"
        >
          权限定义管理
        </el-button>
        <el-button
          :icon="useRenderIcon(Refresh)"
          :loading="loading"
          @click="refresh"
        >
          刷新
        </el-button>
      </div>

      <div class="flex items-center gap-3">
        <template v-if="selectedRole">
          <el-tag type="primary" effect="plain">
            当前角色: {{ selectedRole.name }}
          </el-tag>
          <el-tag :type="checkedCount > 0 ? 'success' : 'info'" effect="plain">
            已分配 {{ checkedCount }} 项权限
          </el-tag>
          <el-tag v-if="hasChanges" type="warning" effect="dark" class="animate-pulse">
            有未保存的更改
          </el-tag>
        </template>
        <template v-else>
          <el-tag type="info" effect="plain">请从左侧选择一个角色</el-tag>
        </template>
      </div>

      <div class="flex items-center gap-2">
        <el-button
          v-if="hasChanges"
          :icon="useRenderIcon(Close)"
          @click="handleReset"
        >
          重置
        </el-button>
        <el-button
          type="primary"
          :icon="useRenderIcon(Check)"
          :loading="saving"
          :disabled="!hasChanges || !selectedRole"
          @click="handleSave"
        >
          保存权限
        </el-button>
      </div>
    </div>

    <!-- 主体区域：分栏布局 -->
    <div class="flex gap-3 px-6 pb-4" style="height: calc(100vh - 200px);">
      <!-- 左栏：角色列表 -->
      <div
        class="left-panel bg-bg_color rounded-lg overflow-hidden flex flex-col"
        style="width: 280px; min-width: 240px;"
      >
        <div class="panel-header px-4 py-3 border-b border-[var(--el-border-color-light)]">
          <h3 class="text-sm font-bold flex items-center gap-2">
            <IconifyIconOffline :icon="Unlock" width="16" />
            角色列表
          </h3>
        </div>

        <div class="p-3">
          <el-input
            v-model="roleSearch"
            placeholder="搜索角色名称/标识..."
            clearable
            :prefix-icon="Search"
            size="small"
          />
        </div>

        <div class="flex-1 overflow-y-auto px-2 pb-2">
          <div
            v-for="role in filteredRoles"
            :key="role.id"
            class="role-item px-3 py-2.5 rounded-lg mb-1 cursor-pointer transition-all duration-200"
            :class="{
              'role-item-active': selectedRole?.id === role.id,
              'role-item-hover': selectedRole?.id !== role.id
            }"
            @click="selectRole(role)"
          >
            <div class="flex items-center justify-between">
              <div class="flex items-center gap-2 min-w-0">
                <div
                  class="w-2 h-2 rounded-full flex-shrink-0"
                  :class="role.status === 1 ? 'bg-green-500' : 'bg-gray-300'"
                />
                <span class="text-sm font-medium truncate">{{ role.name }}</span>
              </div>
              <el-tag size="small" type="info" effect="plain" class="flex-shrink-0 ml-2">
                {{ role.code }}
              </el-tag>
            </div>
            <div class="text-xs text-gray-400 mt-1 pl-4">
              标识: {{ role.code }}
            </div>
          </div>

          <div
            v-if="filteredRoles.length === 0"
            class="flex items-center justify-center py-8 text-gray-400 text-sm"
          >
            <IconifyIconOffline :icon="Search" width="16" class="mr-1" />
            暂无匹配角色
          </div>
        </div>
      </div>

      <!-- 右栏：权限分配面板 -->
      <div class="right-panel bg-bg_color rounded-lg overflow-hidden flex flex-col flex-1">
        <div class="panel-header px-4 py-3 border-b border-[var(--el-border-color-light)] flex items-center justify-between">
          <h3 class="text-sm font-bold flex items-center gap-2">
            <IconifyIconOffline :icon="Unlock" width="16" />
            权限分配
            <span v-if="selectedRole" class="text-gray-400 font-normal">
              — {{ selectedRole.name }}
            </span>
          </h3>

          <div class="flex items-center gap-3">
            <el-input
              v-model="permissionSearch"
              placeholder="搜索权限..."
              clearable
              :prefix-icon="Search"
              size="small"
              style="width: 200px"
            />
          </div>
        </div>

        <div class="flex-1 overflow-y-auto p-4">
          <template v-if="!selectedRole">
            <div class="flex flex-col items-center justify-center h-full text-gray-400">
              <IconifyIconOffline :icon="Unlock" width="48" class="mb-3 opacity-30" />
              <p class="text-sm">请从左侧选择一个角色</p>
              <p class="text-xs mt-1">选择角色后，可在此为其分配权限</p>
            </div>
          </template>

          <template v-else-if="filteredPermissionTree.length === 0 && !loading">
            <div class="flex flex-col items-center justify-center h-full text-gray-400">
              <p class="text-sm">暂无权限数据</p>
            </div>
          </template>

          <template v-else>
            <div v-loading="loading" class="space-y-3">
              <div
                v-for="module in filteredPermissionTree"
                :key="module.id"
                class="module-card border border-[var(--el-border-color-light)] rounded-lg overflow-hidden transition-all duration-200 hover:shadow-sm"
              >
                <!-- 模块表头 -->
                <div
                  class="module-header flex items-center justify-between px-4 py-2.5 cursor-pointer select-none transition-colors duration-150"
                  :class="isModuleIndeterminate(module) || isModuleAllChecked(module)
                    ? 'bg-[var(--el-color-primary-light-9)]'
                    : 'bg-[var(--el-fill-color-light)]'"
                  @click="toggleModuleExpand(module.id)"
                >
                  <div class="flex items-center gap-3">
                    <el-checkbox
                      :model-value="isModuleAllChecked(module)"
                      :indeterminate="isModuleIndeterminate(module)"
                      @change="(val) => toggleModule(module, val as any)"
                      @click.stop
                    />
                    <span class="text-sm font-semibold">{{ module.name }}</span>
                    <el-tag size="small" type="info" effect="plain">
                      {{ module.children?.length || 0 }}项
                    </el-tag>
                  </div>

                  <div class="flex items-center gap-2">
                    <span class="text-xs text-gray-400">
                      已选 {{ module.children?.filter((p: any) => checkedIds.has(p.id)).length || 0 }}
                    </span>
                    <IconifyIconOffline
                      :icon="expandedModules.includes(String(module.id)) ? 'ep:chevron-up' : 'ep:chevron-down'"
                      width="14"
                      class="text-gray-400 transition-transform duration-200"
                    />
                  </div>
                </div>

                <!-- 权限列表 -->
                <template v-if="expandedModules.includes(String(module.id))">
                  <div class="divide-y divide-[var(--el-border-color-light)]">
                    <div
                      v-for="perm in module.children"
                      :key="perm.id"
                      class="permission-item flex items-center justify-between px-4 py-2.5 transition-colors duration-150 hover:bg-[var(--el-color-primary-light-9)]"
                      @click="togglePermission(perm.id, String(module.id))"
                    >
                      <div class="flex items-center gap-3 min-w-0">
                        <el-checkbox
                          :model-value="checkedIds.has(perm.id)"
                          @click.stop
                          @change="() => togglePermission(perm.id, String(module.id))"
                        />
                        <span class="text-sm">{{ perm.name }}</span>
                        <el-tag size="small" :type="getOpTypeTag(perm.operationType || '').type" effect="light">
                          {{ perm.operationType || '未知' }}
                        </el-tag>
                      </div>
                      <el-tooltip :content="perm.permissionCode || ''" placement="left">
                        <code class="text-xs text-gray-400 font-mono truncate max-w-[200px] ml-2">
                          {{ perm.permissionCode || '' }}
                        </code>
                      </el-tooltip>
                    </div>
                  </div>
                </template>
              </div>
            </div>
          </template>
        </div>
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.main {
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.top-bar {
  flex-shrink: 0;
  border-bottom: 1px solid var(--el-border-color-light);
}

.left-panel {
  flex-shrink: 0;

  .role-item {
    border: 1px solid transparent;

    &-active {
      background: var(--el-color-primary-light-9);
      border-color: var(--el-color-primary-light-5);

      .text-sm.font-medium {
        color: var(--el-color-primary);
      }
    }

    &-hover {
      &:hover {
        background: var(--el-fill-color-light);
      }
    }
  }
}

.right-panel {
  min-width: 0;
}

.module-card {
  .module-header {
    &:hover {
      background: var(--el-color-primary-light-9);
    }
  }

  .permission-item {
    cursor: pointer;

    &:hover {
      background: var(--el-color-primary-light-9);
    }

    &:active {
      background: var(--el-color-primary-light-7);
    }
  }
}

// 动画
.animate-pulse {
  animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.6; }
}
</style>
