<script setup lang="ts">
import { computed, ComputedRef, reactive, ref, watch } from "vue";
import { useRole } from "./utils/hook";
import { PureTableBar } from "@/components/RePureTableBar";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";

import Delete from "@iconify-icons/ep/delete";
import EditPen from "@iconify-icons/ep/edit-pen";
import Search from "@iconify-icons/ep/search";
import Refresh from "@iconify-icons/ep/refresh";
import AddFill from "@iconify-icons/ri/add-circle-line";
import { addRoleApi, AddRoleCommand, getRoleInfoApi, RoleDTO, updateRoleApi, UpdateRoleCommand } from "@/api/system/role";
import { ElMessage, FormRules } from "element-plus";
import { MenuDTO } from "@/api/system/menu";

defineOptions({
  name: "SystemRole"
});

const formRef = ref();
const {
  form,
  loading,
  columns,
  dataList,
  activeTab,
  pagination,
  onSearch,
  resetForm,
  menuTree,
  getMenuTree,
  handleDelete
} = useRole();

const opType = ref<"add" | "update">("add");
const opRow = ref<RoleDTO>();
const dataScope = ref<Record<number, string>>({});
(window as any).dataScope = dataScope;

const formData = reactive<AddRoleCommand | UpdateRoleCommand>({
  roleId: 0,
  dataScope: "",
  menuIds: [],
  remark: "",
  roleKey: "",
  roleName: "",
  roleSort: 1,
  status: "1"
});
const resetFromData = () => {
  Object.assign(formData, {
    roleId: 0,
    dataScope: "",
    menuIds: [],
    remark: "",
    roleKey: "",
    roleName: "",
    roleSort: 1,
    status: "1"
  });
}
const rules: FormRules = {
  roleName: [
    {
      required: true,
      message: "角色名称不能为空"
    }
  ],
  roleKey: [
    {
      required: true,
      message: "权限标识不能为空"
    }
  ],
  roleSort: [
    {
      required: true,
      message: "角色序号不能为空"
    }
  ]
};

watch(activeTab, async (val) => {
  // console.log("activeTab", val); // 输出当前选中的标签的 key 或其他标识符
  opRow.value = dataList.value.find(item => item.roleKey == val);
  if (!opRow.value) {
    return;
  }
  await getRoleInfo("update", opRow.value);
  Object.assign(formData, opRow.value);
  formData.menuIds = opRow.value.selectedMenuList;
  updateDataScope(true);
});
async function getRoleInfo(type: "add" | "update", row?: RoleDTO) {
  try {
    await getMenuTree();
    if (row) {
      const { data } = await getRoleInfoApi(row.roleId);
      row.selectedMenuList = data.selectedMenuList;
      row.selectedDeptList = data.selectedDeptList;
    }
  } catch (e) {
    console.error(e);
    ElMessage.error((e as Error)?.message || "加载菜单失败");
  }
  opType.value = type;
  opRow.value = row;
}
const processedMenuOptions = ref<{ id:number, categoryName: string; items: MenuDTO[]; dataScope: string }[]>([]);
(window as any).processedMenuOptions = processedMenuOptions;

// 监听菜单树变化，处理菜单选项结构
watch(menuTree, (val) => {
  // 初始化分类数组
  const categories = [];

  // 收集叶子节点（没有子菜单的节点）
  const collectLeaves = (menu: MenuDTO) => {
    if (!menu.children) return [];
    // 过滤出没有子菜单的子节点
    return menu.children.filter(child => child.children?.length ? false : true);
  };

  // 递归收集菜单项
  const collectMenus = (menuOption: MenuDTO) => {
    // 获取当前菜单的叶子节点
    const leaves = collectLeaves(menuOption);
    // 将当前菜单项添加到叶子节点数组开头
    leaves.unshift(menuOption);

    // 如果有叶子节点，则创建分类
    if (leaves.length) {
      categories.push({
        id: menuOption.id,
        categoryName: menuOption.menuName,
        items: leaves
      });
    }

    // 处理有子菜单的节点
    if (menuOption.children?.length) {
      // 筛选出还有子菜单的子节点
      const lastMenu = menuOption.children.filter(child => child.children?.length);
      // 递归处理这些子节点
      lastMenu.filter(lastMenuOption => lastMenuOption.routerName != 'MenuManagement').forEach(child => {
        collectMenus(child);
      });
    }
  };

  // 遍历菜单树，开始收集菜单项
  // console.log("遍历菜单树 val", val);
  val.forEach(menuOption => {
    collectMenus(menuOption);
  })

  // console.log("categories", categories); // 输出处理后的菜单选项结构，方便调试和查看结构
  // 更新处理后的菜单选项
  processedMenuOptions.value = categories;
});

// 监听菜单选择变化，更新数据权限
const updateDataScope = (updateAll: boolean) => {
  if (updateAll) {
    dataScope.value = {};
  }
  // console.log("updateDataScope formData.menuIds", formData.menuIds);
  processedMenuOptions.value.forEach(category => {
    // 检查是否有任何非“读写”的菜单权限被选中
    const hasSelectedMenu = category.items.some(item => 
      item.menuName !== '读写' && formData.menuIds.includes(item.id)
    );
    // 检查是否有任何“读写”的菜单权限被选中
    const hasWriteSelectedMenu = category.items.some(item =>
      item.menuName == '读写' && formData.menuIds.includes(item.id)
    );
    
    if (hasSelectedMenu && !hasWriteSelectedMenu) {
      // 有选中的菜单权限，默认选中只读
      dataScope.value[category.id] = dataScope.value[category.id] || `${category.id}-0`;
    } else if (hasSelectedMenu && hasWriteSelectedMenu) {
      // 有选中的“读写”菜单权限，默认选中“读写”
      dataScope.value[category.id] = dataScope.value[category.id] || `${category.id}-1`;
    } else {
      // 没有选中的菜单权限，不选中任何数据权限
      dataScope.value[category.id] = null;

      if (hasWriteSelectedMenu) {
        const writeReadItem = category.items.find(item => item.menuName === '读写');
        formData.menuIds = formData.menuIds.filter(id => id !== writeReadItem.id);
      }
    }
  });
};

// 监听dataScope变化，反向更新menuIds
watch(
  dataScope,
  (newDataScope) => {
    Object.entries(newDataScope).forEach(([categoryId, scopeValue]) => {
      if (!scopeValue) {
        return;
      }
      const [id, permission] = scopeValue.split('-');
      const category = processedMenuOptions.value.find(cat => cat.id === Number(id));
      if (!category) return;
      
      const writeReadItem = category.items.find(item => item.menuName === '读写');
      if (!writeReadItem) return;
      
      if (permission === '1') {
        if (!formData.menuIds.includes(writeReadItem.id)) {
          formData.menuIds.push(writeReadItem.id);
        }
      } else {
        formData.menuIds = formData.menuIds.filter(id => id !== writeReadItem.id);
      }
    });
  },
  { deep: true }
);

// 监听菜单选择变化，更新数据权限
watch(() => formData.menuIds,
  () => {
    updateDataScope(false);
  },
  { deep: true }
);

async function handleConfirm() {
  try {
    await formRef.value?.validate();
    loading.value = true;
    formData.dataScope = Object.values(dataScope.value).join(',');
    // console.log("opType", opType.value);
    if (opType.value === 'add') {
      await addRoleApi(formData as AddRoleCommand);
    } else {
      await updateRoleApi(formData as UpdateRoleCommand);
    }
    ElMessage.info("提交成功");
    onSearch().then(() => {
      activeTab.value = dataList.value[0].roleKey;
    });
  } catch (e) {
    console.error(e);
    ElMessage.error((e as Error)?.message || "提交失败");
  } finally {
    loading.value = false;
  }
}
const addRole = async () => {
  await getRoleInfo("add");
  activeTab.value = '';
  resetFromData();
}

getMenuTree();
onSearch().then(() => {
  activeTab.value = dataList.value[0].roleKey;
});
</script>
<template>
  <div class="main">

    <div class="tab-header">
      <el-button :icon="useRenderIcon(AddFill)" @click="addRole" style="margin-bottom: 16px">
        新建角色
      </el-button>
      <ul class="role-list">
        <li v-for="role in dataList" :key="role.roleKey" :class="{ 'active': activeTab === role.roleKey }"
          @click="activeTab = role.roleKey">
          {{ role.roleName }}
        </li>
      </ul>
    </div>
    <el-form :model="formData" label-width="120px" :rules="rules" ref="formRef">
      <el-form-item prop="roleName" label="角色名称" required inline-message>
        <el-input v-model="formData.roleName" class="form-input" />
      </el-form-item>
      <el-form-item prop="roleKey" label="权限字符" required>
        <el-input v-model="formData.roleKey" class="form-input" />
      </el-form-item>
      <!-- <el-form-item prop="roleSort" label="角色顺序" required>
        <el-input-number :min="1" v-model="formData.roleSort" />
      </el-form-item> -->
      <!-- <el-form-item prop="status" label="角色状态">
        <el-radio-group v-model="formData.status">
          <el-radio v-for="item in Object.keys(statusList)" :key="item" :label="statusList[item].value">{{
            statusList[item].label }}</el-radio>
        </el-radio-group>
      </el-form-item> -->
      <div style="display: flex;">
        <div class="form-input-data">
          <div class="menu-container">
            <div class="menu-label">
              <label class="el-form-item__label">数据权限</label>
            </div>
            <template v-for="menu in processedMenuOptions" :key="menu.categoryName">
              <div v-if="menu.items.some(item => item.menuName === '读写')">
                <el-radio-group v-model="dataScope[menu.id]">
                  <el-radio :key="`${menu.id}-0`" :label="`${menu.id}-0`">只读</el-radio>
                  <el-radio :key="`${menu.id}-1`" :label="`${menu.id}-1`">读写</el-radio>
                </el-radio-group>
              </div>
              <div v-else class="empty-placeholder"></div>
              <div class="empty-box"></div>
              <el-divider class="divider" />
            </template>
          </div>
        </div>
        <div prop="menuIds" class="form-input" style="flex: 1;">
          <div class="menu-container">
            <div class="menu-label">
              <label class="el-form-item__label">菜单权限</label>
            </div>
            <el-checkbox-group v-model="formData.menuIds" class="checkbox-group">
              <template v-for="menu in processedMenuOptions" :key="menu.categoryName">
                <el-checkbox v-for="item in menu.items.filter(item => item.menuName != '读写')" :key="item.id" :label="item.id" class="menu-checkbox">

                  {{ item.menuName }}
                </el-checkbox>
                <el-divider class="divider" />
              </template>
            </el-checkbox-group>
          </div>
        </div>
      </div>
      <!-- <el-form-item prop="remark" label="备注" style="margin-bottom: 0">
        <el-input type="textarea" class="form-input" v-model="formData.remark" />
      </el-form-item> -->
      <el-form-item class="form-actions">
        <el-button type="primary" @click="handleConfirm">确认</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<style scoped lang="scss">
.role-list {
  list-style: none;
  padding: 0;
  margin: 0;

  li {
    width: 200px;
    padding: 6px 12px;
    cursor: pointer;
    transition: all 0.3s;
    border-left: 3px solid transparent;
    font-weight: 700;
    font-size: 16px;

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

    &.active {
      background-color: var(--el-color-primary-light-8);
      /* border-left-color: var(--el-color-primary); */
      color: var(--el-color-primary);
    }
  }
}

:deep(.el-dropdown-menu__item i) {
  margin: 0;
}

.search-form {
  :deep(.el-form-item) {
    margin-bottom: 12px;
  }
}

.main {
  display: flex;
  gap: 5px;
}

.tab-header {
  height: 86vh;
  padding: 20px 12px 12px 12px;
  background-color: #FFFFFF;
  flex: 0 0 0px;
}

.el-form {
  height: 86vh;
  padding-top: 20px;
  background-color: #FFFFFF;
  flex: 1;
}

.form-input-data {
  margin-left: 50px;

  .el-radio {
    margin-right: 12px;
  }
}
.form-input {
  width: 40%;
}

.divider {
  margin: 6px 0;

}

.form-actions {
  margin-top: 20px;
  text-align: right;
}

.menu-container {
  border-radius: 4px;
}

.menu-label {
  padding-bottom: 8px;
  margin-bottom: 10px;
  border-bottom: 1px solid #e4e7ed;
}
.empty-placeholder {
  height: 32px;
}
</style>
