package com.fs.common.enums;


import java.util.Arrays;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 数据权限范围枚举
 * 定义系统中不同层级的数据访问权限
 *
 * @author System
 * @date 2024年
 */
public enum DataScopeEnum {

    /**
     * 全部数据权限 - 最高权限级别，可以访问所有数据
     */
    ALL("1", "全部数据权限"),

    /**
     * 自定义数据权限 - 根据用户自定义的权限规则访问数据
     */
    CUSTOM("2", "自定数据权限"),

    /**
     * 本部门数据权限 - 只能访问用户所属部门的数据
     */
    DEPARTMENT("3", "本部门数据权限"),

    /**
     * 本部门及以下数据权限 - 可以访问用户所属部门及其下级部门的数据
     */
    DEPARTMENT_AND_BELOW("4", "本部门及以下数据权限"),
    /**
     * 仅本人数据权限
     */
    SELF_ONLY("5", "仅本人数据权限");

    /**
     * 权限类型代码
     * -- GETTER --
     *  获取权限代码
     *
     * @return 权限代码

     */
    private final String code;

    /**
     * 权限描述信息
     * -- GETTER --
     *  获取权限描述
     *
     * @return 权限描述

     */
    private final String description;


    public String getCode() {
        return code;
    }

    public String getDescription() {
        return description;
    }



    /**
     * 代码到枚举值的映射缓存，用于快速查找
     */
    private static final Map<String, DataScopeEnum> CODE_MAP = Arrays.stream(values())
            .collect(Collectors.toMap(DataScopeEnum::getCode, Function.identity()));

    /**
     * 构造函数
     *
     * @param code 权限代码
     * @param description 权限描述
     */
    DataScopeEnum(String code, String description) {
        this.code = code;
        this.description = description;
    }

    /**
     * 根据代码获取对应的枚举值
     *
     * @param code 权限代码
     * @return 对应的枚举值，如果不存在则返回null
     */
    public static DataScopeEnum getByCode(String code) {
        return CODE_MAP.get(code);
    }

    /**
     * 根据代码获取对应的枚举值，如果不存在则抛出异常
     *
     * @param code 权限代码
     * @return 对应的枚举值
     * @throws IllegalArgumentException 如果代码对应的枚举值不存在
     */
    public static DataScopeEnum getByCodeOrThrow(String code) {
        DataScopeEnum enumValue = CODE_MAP.get(code);
        if (enumValue == null) {
            throw new IllegalArgumentException("无效的数据权限代码: " + code);
        }
        return enumValue;
    }

    /**
     * 验证代码是否有效
     *
     * @param code 待验证的权限代码
     * @return 如果代码有效返回true，否则返回false
     */
    public static boolean isValidCode(String code) {
        return CODE_MAP.containsKey(code);
    }

    /**
     * 获取所有有效的权限代码数组
     *
     * @return 权限代码数组
     */
    public static String[] getAllCodes() {
        return CODE_MAP.keySet().toArray(new String[0]);
    }

    /**
     * 检查当前权限是否包含另一个权限
     * 权限层级关系：ALL > DEPARTMENT_AND_BELOW > DEPARTMENT > CUSTOM
     *
     * @param other 另一个权限
     * @return 如果当前权限包含或等于另一个权限返回true
     */
    public boolean contains(DataScopeEnum other) {
        if (this == ALL) {
            return true; // 全部权限包含所有权限
        }
        if (this == DEPARTMENT_AND_BELOW) {
            return other == DEPARTMENT_AND_BELOW || other == DEPARTMENT || other == CUSTOM;
        }
        if (this == DEPARTMENT) {
            return other == DEPARTMENT || other == CUSTOM;
        }
        return this == other; // CUSTOM 只包含自己
    }

    /**
     * 获取权限的层级值（数值越小权限越大）
     *
     * @return 层级值
     */
    public int getLevel() {
        switch (this) {
            case ALL: return 1;
            case DEPARTMENT_AND_BELOW: return 2;
            case DEPARTMENT: return 3;
            case CUSTOM: return 4;
            default: return 5;
        }
    }

    /**
     * 比较两个权限的层级
     *
     * @param other 另一个权限
     * @return 如果当前权限层级更高返回正数，相同返回0，更低返回负数
     */
    public int compareLevel(DataScopeEnum other) {
        return Integer.compare(other.getLevel(), this.getLevel());
    }

    @Override
    public String toString() {
        return code + ":" + description;
    }
}
