package me.qwq.doghouse.util;

import java.util.HashSet;
import java.util.Set;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import me.qwq.doghouse.annotation.StaticAttribute;
import me.qwq.doghouse.entity.User;

@StaticAttribute
public class SessionUtils {
    
    public static final String LOGIN_USER = "loginUser";
    
    public static final String POST_PASS_JAR = "postPassJar";
    
    public static final String CAPTCHA = "captcha";
    
    public static final String COMMENT_ID_LIST = "commentIdList";
    
    public static final String POST_ID_SET = "postIdSet";
    
    /**
     * 获取当前 Session 中的 User
     * @param request
     * @return
     */
    public static User getUser(HttpServletRequest request) {
        if (request == null) {
            return null;
        }
        return getUser(request.getSession());
    }
    
    /**
     * 获取当前 Session 中的 User
     * @param session
     * @return
     */
    public static User getUser(HttpSession session) {
        if (session == null) {
            return null;
        }
        return (User) session.getAttribute(LOGIN_USER);
    }
    
    /**
     * 将指定 User 设置到 Session 中
     * @param session
     * @param user
     */
    public static void setUser(HttpSession session, User user) {
        AuthenticationManager authenticationManager = SpringContextHolder.getBean("authenticationManager");
        Authentication authentication = authenticationManager.authenticate(
            new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword())
        );
        SecurityContextHolder.getContext().setAuthentication(authentication);
        session.setAttribute("SPRING_SECURITY_CONTEXT", SecurityContextHolder.getContext());
        session.setAttribute(LOGIN_USER, user);
    }
    
    /**
     * 是否登录
     * @param request
     * @return
     */
    public static Boolean isLogin(HttpSession session) {
        return getUser(session) != null;
    }
    
    /**
     * 是否登录
     * @param request
     * @return
     */
    public static Boolean isLogin(HttpServletRequest request) {
        return getUser(request) != null;
    }

    /**
     * 
     * @param request
     * @return
     */
    public static Set<Long> getPostIdSet(HttpServletRequest request) {
        return getPostIdSet(request.getSession());
    }
    
    /**
     * 
     * @param session
     * @return
     */
    public static Set<Long> getPostIdSet(HttpSession session) {
        if (session == null) return new HashSet<>();
        @SuppressWarnings("unchecked")
        Set<Long> postIdSet = (Set<Long>) session.getAttribute(POST_ID_SET);
        if (postIdSet == null) {
            postIdSet = new HashSet<>();
            session.setAttribute(POST_ID_SET, postIdSet);
        }
        return postIdSet;
    }
    
    /**
     * 判断用户 Session 中是否含有指定的 Post  ID
     * @param request
     * @param id
     * @return
     */
    public static Boolean containsPostId(HttpServletRequest request, Long id) {
        return getPostIdSet(request).contains(id);
    }

    /**
     * 判断用户 Session 中是否含有指定的 Post ID
     * @param session
     * @param id
     * @return
     */
    public static Boolean containsPostId(HttpSession session, Long id) {
        return getPostIdSet(session).contains(id);
    }
    
    /**
     * 对指定 HttpServletRequest Session 中添加指定 Post ID，让拥有指定 session 的用户可以访问加密文章
     * @param request
     * @param id
     */
    public static void addPostId(HttpServletRequest request, Long id) {
        addPostId(request.getSession(), id);
    }

    /**
     * 对指定 Session 中添加指定 Post ID，让拥有指定 session 的用户可以访问加密文章
     * @param session
     * @param id
     */ 
    public static void addPostId(HttpSession session, Long id) {
        if (session == null) return;
        Set<Long> postIdSet = getPostIdSet(session);
        postIdSet.add(id);
        session.setAttribute(POST_ID_SET, postIdSet);
    }
    
    /**
     * 从 Session 中获取属于该 Session 的评论 ID 集合
     * @param request
     * @return
     */
    public static Set<Long> getCommentIdSet(HttpServletRequest request) {
        HttpSession session = request.getSession();
        return getCommentIdSet(session);
    }
    
    /**
     * 从 Session 中获取属于该 Session 的评论 ID 集合
     * @param session
     * @return
     */
    public static Set<Long> getCommentIdSet(HttpSession session) {
        if (session == null) return new HashSet<>();
        @SuppressWarnings("unchecked")
        Set<Long> commentIdList = (Set<Long>) session.getAttribute(COMMENT_ID_LIST);
        if (commentIdList == null) {
            commentIdList = new HashSet<>();
            session.setAttribute(COMMENT_ID_LIST, commentIdList);
        }
        return commentIdList;
    }
    
    /**
     * 判断 Session 中是否含有指定的评论 ID
     * @param request
     * @param id
     * @return
     */
    public static Boolean containsCommentId(HttpServletRequest request, Long id) {
        return getCommentIdSet(request).contains(id);
    }

    /**
     * 判断 Session 中是否含有指定的评论 ID
     * @param session
     * @param id
     * @return
     */
    public static Boolean containsCommentId(HttpSession session, Long id) {
        return getCommentIdSet(session).contains(id);
    }
    
    /**
     * 在指定 Session 中添加指定评论 ID, 使得同 session 用户可以管理自己的评论
     * @param request 相关请求, 从中提取 session
     * @param id
     */
    public static void addCommentId(HttpServletRequest request, Long id) {
        addCommentId(request.getSession(), id);
    }

    /**
     * 在指定 Session 中添加指定评论 ID, 使得同 session 用户可以管理自己的评论
     * @param session 相关 session
     * @param id
     */ 
    public static void addCommentId(HttpSession session, Long id) {
        if (session == null) return;
        Set<Long> commentIdList = getCommentIdSet(session);
        commentIdList.add(id);
        session.setAttribute(COMMENT_ID_LIST, commentIdList);
    }

}
