package shop.alien.store.filter;

import com.alibaba.fastjson.JSONObject;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import shop.alien.entity.store.LifeSysMenu;
import shop.alien.entity.store.LifeSysRole;
import shop.alien.mapper.LifeSysMenuMapper;
import shop.alien.store.service.impl.LifeSysRoleServiceImpl;
import shop.alien.util.common.JwtUtil;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class PreAuthFilter extends OncePerRequestFilter {
    // 自定义权限请求头（前端传递角色/权限）
    private static final String USER_TOKEN_HEADER = "Authorization";
    private static final String PLATFORM_TYPE_HEADER = "X-platform-type";

    @Resource
    private LifeSysMenuMapper lifeSysMenuMapper;
    @Resource
    private LifeSysRoleServiceImpl lifeSysRoleServiceImpl;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        // 1. 从请求头获取角色信息（前端传递，比如：ROLE_ADMIN,ROLE_USER）
        String token = request.getHeader(USER_TOKEN_HEADER);
        String platformType = request.getHeader(PLATFORM_TYPE_HEADER);

        /**
         * 如果不是平台端请求，直接放行，加admin权放行
         */
        if(null == platformType || !"platform".equalsIgnoreCase(platformType)) {
            UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
                    "notPlatformUser", // 无认证场景，用户名可自定义
                    null, // 无需密码，置空
                    AuthorityUtils.commaSeparatedStringToAuthorityList(String.join(",", "ROLE_ADMIN")));// 权限列表
            chain.doFilter(request, response);
            return;
        }

        if (token == null) {
            // 无权限头：视为匿名用户（仅能访问公开接口）
            chain.doFilter(request, response);
            return;
        }

        // 2. 解析角色为权限集合（Spring Security 角色需以ROLE_开头）
        JSONObject tokenInfo = JwtUtil.getTokenInfo(token);
        String userId = tokenInfo.getString("userId");
        String userName = tokenInfo.getString("userName");
        List<LifeSysMenu> menuByUserId = lifeSysMenuMapper.getMenuByUserId(Long.parseLong(userId));
        List<String> permsList = menuByUserId.stream().map(LifeSysMenu::getPerms).collect(Collectors.toList());
        List<LifeSysRole> roleByUserId = lifeSysRoleServiceImpl.getRoleByUserId(Long.parseLong(userId));
        List<String> roleList = roleByUserId.stream().map(x->"ROLE_"+x.getRoleNameEn().toUpperCase()).collect(Collectors.toList());
        permsList.addAll(roleList);
        // 3. 构建认证令牌（用户名可固定/自定义，密码置空，核心是权限）
        UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
                userName, // 无认证场景，用户名可自定义
                null, // 无需密码，置空
                AuthorityUtils.commaSeparatedStringToAuthorityList(String.join(",", permsList)));// 权限列表
        // 4. 设置请求上下文
        authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
        // 5. 将认证信息存入SecurityContext（标记用户已"认证"，仅用于授权）
        SecurityContextHolder.getContext().setAuthentication(authToken);

        // 继续执行过滤器链
        chain.doFilter(request, response);
    }
}
