package com.ruoyi.web.report.service.impl;

import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.report.domain.ErpReportDefinition;
import com.ruoyi.web.report.mapper.ReportMenuMapper;
import com.ruoyi.web.report.service.IReportDynamicMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 报表发布动态菜单服务实现。
 */
@Service
public class ReportDynamicMenuServiceImpl implements IReportDynamicMenuService {
    /** 用户端统一页面组件。 */
    private static final String USER_COMPONENT = "erp/report/index";
    /** 菜单权限。 */
    private static final String USER_PERMS = "erp:report:query";

    @Autowired
    private ReportMenuMapper reportMenuMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createOrUpdateReportMenu(ErpReportDefinition definition, String operator) {
        if (definition == null || definition.getId() == null) {
            throw new IllegalArgumentException("发布菜单失败：报表信息不能为空。");
        }
        Long rootMenuId = ensureRootMenu(operator);
        String menuName = StringUtils.isEmpty(definition.getReportName()) ? ("报表-" + definition.getId()) : definition.getReportName();
        String safeCode = normalizeCode(definition.getReportCode(), definition.getId());
        String menuPath = "erpReport_" + safeCode;
        String queryText = buildMenuQueryJson(definition.getId());

        Long menuId = reportMenuMapper.selectMenuIdByParentAndPath(rootMenuId, menuPath);
        if (menuId == null) {
            Integer maxOrder = reportMenuMapper.selectMaxOrderNumByParentId(rootMenuId);
            int orderNum = (maxOrder == null ? 0 : maxOrder) + 1;
            reportMenuMapper.insertMenu(menuName, rootMenuId, orderNum, menuPath, USER_COMPONENT, queryText, USER_PERMS, "table", operator);
            Long newMenuId = reportMenuMapper.selectLastInsertMenuId();
            if (newMenuId == null) {
                throw new IllegalStateException("发布菜单失败：无法获取新建菜单ID。");
            }
            safeSyncBinding(definition, newMenuId, menuPath, queryText, operator, false);
            grantMenuPermissions(newMenuId, operator);
            return;
        }
        reportMenuMapper.updateMenuById(menuId, menuName, menuPath, USER_COMPONENT, queryText, "0", operator);
        safeSyncBinding(definition, menuId, menuPath, queryText, operator, true);
        grantMenuPermissions(menuId, operator);
    }

    /**
     * 菜单 path 仅保留安全字符，避免路由异常。
     */
    private String normalizeCode(String reportCode, Long reportId) {
        String source = StringUtils.isEmpty(reportCode) ? String.valueOf(reportId) : reportCode;
        String normalized = source.replaceAll("[^a-zA-Z0-9_]", "_");
        if (StringUtils.isEmpty(normalized)) {
            return String.valueOf(reportId);
        }
        return normalized;
    }

    /**
     * 确保报表中心根目录存在，并授权管理员。
     */
    private Long ensureRootMenu(String operator) {
        Long rootMenuId = reportMenuMapper.selectRootMenuId();
        if (rootMenuId == null) {
            reportMenuMapper.insertRootMenu(StringUtils.isEmpty(operator) ? "system" : operator);
            rootMenuId = reportMenuMapper.selectLastInsertMenuId();
            if (rootMenuId == null) {
                throw new IllegalStateException("自动创建报表中心目录失败。");
            }
        }
        grantMenuPermissions(rootMenuId, operator);
        return rootMenuId;
    }

    /**
     * 绑定表为辅助信息，缺失时不影响菜单主流程。
     */
    private void safeSyncBinding(
            ErpReportDefinition definition,
            Long menuId,
            String menuPath,
            String queryText,
            String operator,
            boolean update
    ) {
        try {
            if (update) {
                reportMenuMapper.updateMenuBinding(definition.getId(), menuId, menuPath, USER_COMPONENT, queryText, operator);
            } else {
                reportMenuMapper.insertMenuBinding(definition.getId(), menuId, menuPath, USER_COMPONENT, queryText, operator);
            }
        } catch (Exception ignored) {
            // 忽略绑定表异常，保证菜单创建/更新与授权可继续完成。
        }
    }

    /**
     * 授权策略：保留 role_id=1 兼容，同时给当前操作者所属角色授权。
     */
    private void grantMenuPermissions(Long menuId, String operator) {
        reportMenuMapper.insertAdminRoleMenuIfAbsent(menuId);
        if (!StringUtils.isEmpty(operator)) {
            reportMenuMapper.insertRoleMenusByUserNameIfAbsent(operator, menuId);
        }
    }

    /**
     * 若依侧边栏会将 menu.query 按 JSON 解析，这里统一输出 JSON 字符串。
     */
    private String buildMenuQueryJson(Long reportId) {
        // 同时保留 reportI 兼容字段，避免历史页面读取差异导致参数丢失。
        return "{\"reportId\":" + reportId + ",\"reportI\":" + reportId + "}";
    }
}
