package org.example.Entity.System;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.servlet.http.HttpServletRequest;
import org.example.Enums.SystemTypeEnums;
import org.example.Utils.DataTableUtil;
import org.example.Utils.PublicUtil;

import java.util.*;

import static org.example.Utils.NativeExtensionUtils.ToInt32;
import static org.example.Utils.NativeExtensionUtils.toBoolean;

public class SystemMenu {

    private Map<String, Object> _row;
    private List<Map<String, Object>> _soure;
    private LoginUserInfo user;
    private String _text;
    private String _moduleId;
    public Integer _serverId; // C#中为public int?，Java用Integer表示可空
    private String _moduleId1;
    private String _menuStruct;
    private boolean _converted = false;
    private String _library;
    private String href;
    private String idValue;
    private Object pagePms;
    private String _defaultImage;
    private String _hoverImage;
    private String _hoverMenuTip;
    private String _billFlag;
    private int _orderId = -1;
    private List<SystemMenu> _children;


    // =========================== 构造方法（与C#逻辑对齐）===========================
    // 私有无参构造（禁止外部直接实例化）
    private SystemMenu() {
    }

    // 双参数构造
    public SystemMenu(Map<String, Object> row, LoginUserInfo user) {
        super();
        this._row = row;
        this.user = user;
    }

    // 三参数构造
    public SystemMenu(Map<String, Object> row, List<Map<String, Object>> soure, LoginUserInfo user) {
        super();
        this._row = row;
        this._soure = soure;
        this.user = user;
    }


    // =========================== 属性：ctx（替代C# HttpContext.Current）===========================
    // 注：Java Web中需通过请求上下文获取，此处模拟C#逻辑（若用Spring可替换为RequestContextHolder）
    private HttpServletRequest getCtx() {
        // 实际项目需根据框架调整（如Spring：RequestContextHolder.getRequestAttributes().getRequest()）
        return null;
    }


    // =========================== 核心属性（按C#逻辑实现）===========================

    /**
     * MenuId：从Map<String,Object>取"id"/"menuid"字段，默认0
     */
    @JsonProperty("MenuId")
    public Integer getMenuId() {
        Object value = DataTableUtil.getRowVal(_row, new String[]{"id", "MenuId"}, 0);
        return ToInt32(value); // 替代C# ToInt32()，需自定义工具方法
    }

    /**
     * GroupCaption：从Map<String,Object>取"GroupCaption"字段，默认null
     */
    @JsonProperty("GroupCaption")
    public String getGroupCaption() {
        Object value = DataTableUtil.getRowVal(_row, "GroupCaption", null);
        return value == null ? null : value.toString();
    }

    /**
     * text：JSON序列化忽略null，优先取_userText，否则从Map<String,Object>取"MenuCaption"
     */
    @JsonInclude(JsonInclude.Include.NON_NULL) // 替代Newtonsoft NullValueHandling.Ignore
    @JsonProperty("text")
    public String getText() {
        if (_text == null) {
            Object value = DataTableUtil.getRowVal(_row, "MenuCaption", null);
            _text = value == null ? null : value.toString();
        }
        return _text;
    }

    public void setText(String text) {
        this._text = text;
    }

    /**
     * ModuleId：复杂逻辑（解析URL参数、提取moduleId等）
     */
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("ModuleId")
    public String getModuleId() {
        // 优先使用已设置的值，否则从Map<String,Object>取"MenuCode"
        if (_moduleId == null) {
            Object value = DataTableUtil.getRowVal(_row, "MenuCode", null);
            _moduleId = value == null ? null : value.toString();
        }

        // 解析包含"app.html"的URL参数（过滤username/password，提取xtype/moduleId等）
        if (_moduleId != null && _moduleId.contains("app.html")) {
            try {
                Map<String, String> queryPms = new HashMap<>();
                String[] urlParts = _moduleId.split("\\?"); // Java中?需转义
                if (urlParts.length > 1) {
                    String queryStr = urlParts[1];
                    String[] kvPairs = queryStr.split("&");
                    for (String kvStr : kvPairs) {
                        String[] kvs = kvStr.split("=");
                        // 过滤username/password，且确保键值对完整
                        if (kvs.length == 2
                                && !"username".equals(kvs[0].toLowerCase())
                                && !"password".equals(kvs[0].toLowerCase())) {
                            queryPms.put(kvs[0].toLowerCase(), kvs[1]);
                        }
                    }
                }

                // 提取xtype/moduleId/idValue等参数
                if (queryPms.containsKey("xtype")) {
                    String moduleId = queryPms.getOrDefault("moduleid",
                            queryPms.getOrDefault("dllcoid", ""));
                    if (!moduleId.isEmpty()) {
                        this._moduleId = moduleId; // 更新ModuleId
                        this._library = queryPms.get("xtype");
                        this.idValue = queryPms.getOrDefault("idvalue",
                                queryPms.getOrDefault("id", ""));
                    }
                    this.pagePms = queryPms;
                }
            } catch (Exception e) {
                // 原C#空catch，Java保留相同逻辑（实际项目建议日志打印）
            }
        }
        return _moduleId;
    }

    public void setModuleId(String moduleId) {
        this._moduleId = moduleId;
    }

    /**
     * serverId：可空int，优先取已设置值，否则从Map<String,Object>取"serverid"（默认0）
     */
    @JsonProperty("serverId")
    public Integer getServerId() {
        if (_serverId == null) {
            Object value = _row.getOrDefault("serverid", "0"); // 假设Map<String,Object>有get(key, defaultValue)方法
            _serverId = ToInt32(value);
        }
        return _serverId > 0 ? _serverId : null;
    }

    public void setServerId(Integer serverId) {
        this._serverId = serverId;
    }

    /**
     * ModuleId1：从Map<String,Object>取"MenuCode1"，默认null
     */
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("ModuleId1")
    public String getModuleId1() {
        if (_moduleId1 == null) {
            Object value = DataTableUtil.getRowVal(_row, "MenuCode1", null);
            _moduleId1 = value == null ? null : value.toString();
        }
        return _moduleId1;
    }

    public void setModuleId1(String moduleId1) {
        this._moduleId1 = moduleId1;
    }

    /**
     * MenuStruct：从Map<String,Object>取"MenuStruct"，默认null
     */
    @JsonProperty("MenuStruct")
    @JsonInclude(JsonInclude.Include.NON_NULL)
    public String getMenuStruct() {
        if (_menuStruct == null) {
            Object value = DataTableUtil.getRowVal(_row, "MenuStruct", null);
            _menuStruct = value == null ? null : value.toString();
        }
        return _menuStruct;
    }

    public void setMenuStruct(String menuStruct) {
        this._menuStruct = menuStruct;
    }

    /**
     * ParentId：从Map<String,Object>取"ParentId"（默认0），转字符串返回
     */
    @JsonProperty("ParentId")
    public String getParentId() {
        return Objects.toString(DataTableUtil.getRowVal(_row, "ParentId", 0), "");
    }

    /**
     * Level：从Map<String,Object>取"level"（默认0），JSON序列化忽略
     */
    @JsonIgnore // 替代Newtonsoft.Json.JsonIgnore
    public int getLevel() {
        Object value = DataTableUtil.getRowVal(_row, "level", 0);
        return ToInt32(value);
    }

    /**
     * ModuleName：关联_library，含ConvertToModuleName逻辑，JSON序列化忽略null
     */
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("ModuleName")
    public String getModuleName() {
        // 优先取已设置值，否则从Map<String,Object>取"Library"
        if (_library == null) {
            Object value = DataTableUtil.getRowVal(_row, "Library", null);
            _library = value == null ? null : value.toString();
        }

        // 仅转换一次（_converted标记）
        if (!_converted) {
            boolean[] isUrl = new boolean[1]; // Java无out参数，用数组接收
            _library = convertToModuleName(_library, 1, isUrl);
            _converted = true;
            // 若为URL，同步设置href
            if (isUrl[0]) {
                this.href = _library;
            }
        }
        return _library;
    }

    public void setModuleName(String moduleName) {
        this._library = moduleName;
    }

    // =========================== 其他简单属性（直接映射）===========================
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("href")
    public String getHref() {
        return href;
    }

    public void setHref(String href) {
        this.href = href;
    }

    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("idValue")
    public String getIdValue() {
        return idValue;
    }

    public void setIdValue(String idValue) {
        this.idValue = idValue;
    }

    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("pagePms")
    public Object getPagePms() {
        return pagePms;
    }

    public void setPagePms(Object pagePms) {
        this.pagePms = pagePms;
    }

    /**
     * ReadAble：用户查看权限判断（优先级：用户ID→角色ID→操作权限）
     */
    @JsonProperty("ReadAble")
    public boolean isReadAble() {
        boolean has = true;
        String readUserIds = getReadUserIds();

        // 1. 优先判断"查看用户IDs"
        if (readUserIds != null && !readUserIds.isEmpty()) {
            has = ("," + readUserIds + ",").contains("," + user.UserId + ",");
        }

        // 2. 无用户权限时，判断"查看角色IDs"
        if ((!has || (readUserIds == null || readUserIds.isEmpty()))
                && getRoleReadIds() != null && !getRoleReadIds().isEmpty()) {
            has = isRoleReadAble();
        }

        // 3. 前两者无权限时，判断操作权限
        if (!has && ((getOperuserIds() != null && !getOperuserIds().isEmpty())
                || (getRoleOperIds() != null && !getRoleOperIds().isEmpty()))) {
            return isOperAble();
        }

        return has;
    }

    /**
     * OperAble：用户操作权限判断（优先级：用户ID→角色ID）
     */
    @JsonProperty("OperAble")
    public boolean isOperAble() {
        boolean has = true;
        String operUserIds = getOperuserIds();

        // 1. 优先判断"操作用户IDs"
        if (operUserIds != null && !operUserIds.isEmpty()) {
            has = ("," + operUserIds + ",").contains("," + user.UserId + ",");
        }

        // 2. 无用户权限时，判断"操作角色IDs"
        if ((!has || (operUserIds == null || operUserIds.isEmpty()))
                && getRoleOperIds() != null && !getRoleOperIds().isEmpty()) {
            return isRoleOperAble();
        }

        return has;
    }

    /**
     * ReadUserIds：私有属性，从Map<String,Object>取"ReadPurview"
     */
    @JsonProperty("ReadUserIds")
    private String getReadUserIds() {
        Object value = DataTableUtil.getRowVal(_row, "ReadPurview", null);
        return value == null ? null : value.toString();
    }

    /**
     * OperuserIds：私有属性，从Map<String,Object>取"OperPurview"
     */
    @JsonProperty("OperuserIds")
    private String getOperuserIds() {
        Object value = DataTableUtil.getRowVal(_row, "OperPurview", null);
        return value == null ? null : value.toString();
    }

    /**
     * RoleReadAble：角色查看权限判断
     */
    @JsonProperty("RoleReadAble")
    public boolean isRoleReadAble() {
        boolean has = true;
        String roleReadIds = getRoleReadIds();

        if (roleReadIds != null && !roleReadIds.isEmpty()) {
            has = false;
            String[] userRoles = user.getRoleIds(); // 假设LoginUserInfo的roleIds是String数组
            if (userRoles != null && userRoles.length > 0) {
                for (String role : roleReadIds.split(",")) {
                    for (String userRole : userRoles) {
                        if (role.equals(userRole)) {
                            has = true;
                            break;
                        }
                    }
                    if (has) break;
                }
            }
        }

        // 无角色查看权限时，判断角色操作权限
        if (!has && getRoleOperIds() != null && !getRoleOperIds().isEmpty()) {
            return isRoleOperAble();
        }

        return has;
    }

    /**
     * RoleOperAble：角色操作权限判断
     */
    @JsonProperty("RoleOperAble")
    public boolean isRoleOperAble() {
        boolean has = true;
        String roleOperIds = getRoleOperIds();

        if (roleOperIds != null && !roleOperIds.isEmpty()) {
            has = false;
            String[] userRoles = user.getRoleIds();
            if (userRoles != null && userRoles.length > 0) {
                for (String role : roleOperIds.split(",")) {
                    for (String userRole : userRoles) {
                        if (role.equals(userRole)) {
                            has = true;
                            break;
                        }
                    }
                    if (has) break;
                }
            }
        }

        return has;
    }

    /**
     * RoleReadIds：私有属性，从Map<String,Object>取"RoleReadPurview"
     */
    @JsonProperty("RoleReadIds")
    private String getRoleReadIds() {
        Object value = DataTableUtil.getRowVal(_row, "RoleReadPurview", null);
        return value == null ? null : value.toString();
    }

    /**
     * RoleOperIds：私有属性，从Map<String,Object>取"RoleOperPurview"
     */
    @JsonProperty("RoleOperIds")
    private String getRoleOperIds() {
        Object value = DataTableUtil.getRowVal(_row, "RoleOperPurview", null);
        return value == null ? null : value.toString();
    }

    /**
     * AppUseAble：从Map<String,Object>取"AppUseFlag"，取反返回（JSON忽略）
     */
    @JsonIgnore
    public boolean isAppUseAble() {
        Object value = DataTableUtil.getRowVal(_row, "AppUseFlag", null);
        return !toBoolean(value); // 替代C# ToBoolean()
    }

    /**
     * ShowCount：从Map<String,Object>取"needcount"，转布尔值
     */
    @JsonProperty("ShowCount")
    public boolean isShowCount() {
        Object value = DataTableUtil.getRowVal(_row, "needcount", null);
        return toBoolean(value);
    }

    /**
     * DefaultImage：从Map<String,Object>取"DefaultImage"，默认null
     */
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("DefaultImage")
    public String getDefaultImage() {
        if (_defaultImage == null) {
            Object value = DataTableUtil.getRowVal(_row, "DefaultImage", null);
            _defaultImage = value == null ? null : value.toString();
        }
        return _defaultImage;
    }

    public void setDefaultImage(String defaultImage) {
        this._defaultImage = defaultImage;
    }

    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("HoverImage")
    public String getHoverImage() {
        if (_hoverImage == null) {
            Object value = DataTableUtil.getRowVal(_row, "HoverImage", null);
            _hoverImage = value != null ? value.toString() : null; // 一行完成判空+赋值
        }
        return _hoverImage;
    }

    public void setHoverImage(String hoverImage) {
        this._hoverImage = hoverImage;
    }

    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("HoverMenuTip")
    public String getHoverMenuTip() {
        if (_hoverMenuTip == null) {
            Object value = DataTableUtil.getRowVal(_row, "HoverMenuTip", null);
            _hoverMenuTip = value != null ? value.toString() : null; // 一行完成判空+赋值
        }
        return _hoverMenuTip;
    }

    public void setHoverMenuTip(String hoverMenuTip) {
        this._hoverMenuTip = hoverMenuTip;
    }

    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("BillFlag")
    public String getBillFlag() {
        if (_billFlag == null) {
            Object value = DataTableUtil.getRowVal(_row, "BillFlag", null);
            _billFlag = value != null ? value.toString() : null; // 一行完成判空+赋值
        }
        return _billFlag;
    }

    public void setBillFlag(String billFlag) {
        this._billFlag = billFlag;
    }

    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("OrderId")
    public Integer getOrderId() {
        if (_orderId==-1){
            Object value = DataTableUtil.getRowVal(_row, "OrderID", null);
            _orderId=value != null ? ToInt32(value) : _orderId; ;
        }
        return _orderId;
    }

    public void setOrderId(Integer orderId) {
        this._orderId = orderId;
    }

    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonProperty("Children")
    public List<SystemMenu> getChildren() {
        // 1. 对应 C#: if (_soure != null)
        if (_soure != null && !_soure.isEmpty()) {
            // 2. 对应 C#: _children ?? (_children = ...) → 懒加载+缓存
            if (_children == null) {
                _children = new ArrayList<>();
                // 3. 遍历 _source（对应 C#: from row in _soure.AsEnumerable()）
                for (Map<String, Object> row : _soure) {
                    // 4. 筛选条件：(row["ParentId"] + "") == MenuId + ""（对齐 C# 的 where 条件）
                    String parentId = DataTableUtil.getStringValue(row, "ParentId"); // 行的ParentId转字符串
                    String currentMenuId = this.getMenuId() != null ? this.getMenuId().toString() : ""; // 当前菜单ID转字符串

                    // 匹配条件：子菜单的ParentId = 当前菜单的MenuId
                    if (Objects.equals(parentId, currentMenuId)) {
                        // 5. 对应 C#: select new SystemMenu(row, _soure, user)
                        SystemMenu childMenu = new SystemMenu(row, _soure, this.user);
                        _children.add(childMenu);
                    }
                }
            }
        }
        // 6. 对应 C#: _soure 为null时返回 _children
        return _children;
    }

    public void setChildren(List<SystemMenu> children) {
        this._children = children;
    }

    public static String convertToModuleName(String dllName, Integer dllType, boolean[] isUrl) {
        // 初始化输出参数
        isUrl[0] = false;

        // 处理空值并转换为小写
        String name = "";
        String lwDllName = (dllName == null ? "" : dllName).trim()
                .replace("\r\n", "")
                .toLowerCase();

        // 空值检查
        if (dllName == null || dllName.trim().isEmpty()) {
            return "";
        }

        // 判断是否为 URL
        if (dllName.startsWith("http") || dllName.startsWith("www")
                || dllName.startsWith("ftp") || dllName.startsWith("/")
                || dllName.indexOf(".html?") > -1) {
            isUrl[0] = true;
            Map<String, Object> pms = new HashMap<>();
            return PublicUtil.ReqSqlPms(null, null, dllName, SystemTypeEnums.PmType.sql, null);
        }

        // 检查是否为 .dll 或 .lsp 文件
        if (!lwDllName.endsWith(".dll") && !lwDllName.endsWith(".lsp")) {
            return dllName;
        }

        // 处理特定 DLL 名称
        if (lwDllName.equals("miniblink.dll")) {
            return "plugins.PubBrower.Index";
        }
        if (lwDllName.equals("lskj.billinfo.dll")) {
            return "plugins.pubbillinfo.Index";
        }

        // 通用处理逻辑
        name = lwDllName.replace("_", ".");
        String[] dlls = name.split("\\.");  // 注意：Java 中.需要转义

        if (dlls.length == 3 && name.startsWith("lskj")) {
            name = name.replace(".dll", ".index");
        }

        name = name.replace("lskj.", "plugins.").replace(".dll", "");

        // 处理特殊名称
        if (name.contains("pubadd")) {
            name = "plugins.PubModule.PubAdd";
        } else if (name.equals("pubspec")) {
            name = "plugins.pubspec.index";
        } else if (name.equals("leftgridiframe")) {
            name = "plugins.leftgridiframe.index";
        } else if (name.contains("pubprint.lsp")) {
            name = "plugins.pubprint.index";
        } else if (name.endsWith(".lsp")) {
            name = name.replace("\\", ".").replace(".lsp", "");
        }

        return name;
    }
}
