package cn.iocoder.byzs.framework.tenant.core.security;

import cn.iocoder.byzs.framework.common.pojo.CommonResult;
import cn.iocoder.byzs.framework.common.util.servlet.ServletUtils;
import cn.iocoder.byzs.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.byzs.framework.web.core.util.WebFrameworkUtils;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import static cn.iocoder.byzs.framework.common.exception.enums.GlobalErrorCodeConstants.FORBIDDEN;

/**
 * 租户数据安全过滤器
 * 用于防止用户修改不属于自己租户的数据
 */
public class TenantDataSecurityFilter extends OncePerRequestFilter {

    // 修改操作的HTTP方法
    private static final Set<String> MODIFY_METHODS = new HashSet<>(Arrays.asList("POST", "PUT", "DELETE", "PATCH"));

    // 不参与SQL拼接的特定方法路径
    private static final Set<String> EXCLUDED_METHOD_PATHS = new HashSet<>(Arrays.asList(
            "/system/",//系统请求
            "/bjdxWeb/web/",//系统请求

//            "/bjdxWeb/questionnaire/",//问卷试题
//            "/bjdxReport/progress/",//评估

            "/ai/chat/conversation/my-list",//对话记录
            "/ai/image/my-page",//绘画记录
            "/ai/chat/conversation/page",//对话列表
            "/ai/image/page",//绘画列表
            "/ai/write/page",//创作列表
            "/ai/mind-map/page"//思维导图列表
    ));

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
//        // 首先检查是否isExcludedPath(request)为需要排除的路径
//        if (request.getMethod().equalsIgnoreCase("GET")) {
//
//            return;
//        }
        if (isExcludedPath(request)) {
            // 对于排除的路径，完全忽略租户过滤，确保只返回单条记录
            boolean splice = TenantContextHolder.isSplice();
            try {
                TenantContextHolder.setSplice(true);
                chain.doFilter(request, response);

                return; // 直接返回，不再执行后续的过滤逻辑
            } finally {
                // 恢复原始状态
                TenantContextHolder.setSplice(splice);
            }
        }

        // 请求数据的租户id
        String dataTenantId = request.getHeader(WebFrameworkUtils.HEADER_DATA_TENANT_ID);

        // 获取当前请求的租户ID
        Long currentTenantId = TenantContextHolder.getTenantId();
        if (dataTenantId != null && currentTenantId != null && !dataTenantId.equals(currentTenantId.toString())) {
            ServletUtils.writeJSON(response, CommonResult.error(FORBIDDEN.getCode(),
                    "不允许修改非本租户的数据"));
            return;
        }
        // 如果是默认租户1，直接放行
        if (WebFrameworkUtils.DEFAULT_TENANT_ID.equals(currentTenantId)) {
            chain.doFilter(request, response);
            return;
        }

        // 在数据访问层，会根据TenantContextHolder.getTenantId()获取当前租户ID，并拼接待查询的租户ID列表
        chain.doFilter(request, response);
    }

    /**
     * 判断当前请求路径是否为不参与SQL拼接的特定方法路径
     */
    private boolean isExcludedPath(HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        if (requestURI.contains("bjdxWeb/web/getRoleRoute") ||
                requestURI.contains("/bjdxWeb/web/getUserInfo") ||
                requestURI.contains("/bjdxWeb/web/register") ||
                requestURI.contains("/bjdxWeb/web/activateInviteCode") ) {
            return false;
        }
        return EXCLUDED_METHOD_PATHS.stream().anyMatch(path -> requestURI.contains(path));
    }
}