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

import com.ruoyi.web.report.domain.bo.ErpReportQueryBo;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

/**
 * 报表运行态参数守卫。
 *
 * <p>用于在进入真正查询执行前统一做参数规范化与安全兜底（分页协议：pageNum/pageSize），
 * 避免控制器和业务服务中重复处理边界条件。</p>
 */
@Component
public class ErpReportRuntimeGuard {

    /** 默认页码。 */
    private static final int DEFAULT_PAGE_NUM = 1;
    /** 默认每页条数。 */
    private static final int DEFAULT_PAGE_SIZE = 20;
    /** 每页条数上限，防止一次拉取过大数据导致慢查询。 */
    private static final int MAX_PAGE_SIZE = 500;
    /** 允许的过滤操作符。 */
    private static final Set<String> SAFE_FILTER_OP =
            new HashSet<>(Arrays.asList("=", "!=", ">", ">=", "<", "<=", "like", "in", "between"));
    /** 允许的排序方向。 */
    private static final Set<String> SAFE_SORT_DIR = new HashSet<>(Arrays.asList("asc", "desc"));

    /**
     * 规范化查询参数。
     *
     * @param queryBo 原始请求参数
     * @return 规范化后的参数（原对象或新对象）
     */
    public ErpReportQueryBo normalize(ErpReportQueryBo queryBo) {
        if (queryBo == null) {
            queryBo = new ErpReportQueryBo();
        }
        if (queryBo.getPageNum() == null || queryBo.getPageNum() < 1) {
            queryBo.setPageNum(DEFAULT_PAGE_NUM);
        }
        if (queryBo.getPageSize() == null || queryBo.getPageSize() < 1) {
            queryBo.setPageSize(DEFAULT_PAGE_SIZE);
        } else if (queryBo.getPageSize() > MAX_PAGE_SIZE) {
            queryBo.setPageSize(MAX_PAGE_SIZE);
        }
        // 过滤条件守卫：限制 operator，避免任意 SQL 片段注入。
        if (queryBo.getFilters() != null) {
            for (Map<String, Object> filter : queryBo.getFilters()) {
                if (filter == null) {
                    continue;
                }
                Object opObj = filter.get("op");
                if (opObj == null) {
                    throw new IllegalArgumentException("过滤条件缺少 op。");
                }
                String op = String.valueOf(opObj).toLowerCase(Locale.ROOT);
                if (!SAFE_FILTER_OP.contains(op)) {
                    throw new IllegalArgumentException("不支持的过滤操作符: " + opObj);
                }
            }
        }
        // 排序条件守卫：仅允许 asc/desc。
        if (queryBo.getSorts() != null) {
            for (Map<String, String> sort : queryBo.getSorts()) {
                if (sort == null || sort.get("direction") == null) {
                    continue;
                }
                String direction = sort.get("direction").toLowerCase(Locale.ROOT);
                if (!SAFE_SORT_DIR.contains(direction)) {
                    throw new IllegalArgumentException("不支持的排序方向: " + sort.get("direction"));
                }
            }
        }
        return queryBo;
    }
}
