package cn.reghao.tnb.auth.app.security.session;

import cn.reghao.tnb.common.web.ServletUtil;
import cn.reghao.tnb.auth.api.constant.TokenType;
import cn.reghao.tnb.auth.app.security.form.AccountAuthToken;
import cn.reghao.tnb.auth.app.service.AccountTokenService;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.context.HttpRequestResponseHolder;
import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.stereotype.Component;

import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

/**
 * 提供给 SecurityContextPersistenceFilter 使用的 SecurityContextRepository 实现
 *
 * @author reghao
 * @date 2023-08-11 10:20:17
 */
@Component
public class MySecurityContextRepository implements SecurityContextRepository {
    private final String cookieName = "USERDATA";
    private final AccountTokenService accountTokenService;

    public MySecurityContextRepository(AccountTokenService accountTokenService) {
        this.accountTokenService = accountTokenService;
    }

    @Override
    public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) {
        HttpServletRequest request = requestResponseHolder.getRequest();
        String token = ServletUtil.getBearerToken(request);
        SecurityContext context = null;
        if (token != null) {
            context = readSecurityContext(TokenType.token.getValue(), token);
        } else {
            Cookie cookie = ServletUtil.getCookie1(cookieName, request);
            if (cookie != null) {
                int maxAge = cookie.getMaxAge();
                context = readSecurityContext(TokenType.cookie.getValue(), cookie.getValue());
            }
        }

        if (context == null) {
            context = SecurityContextHolder.createEmptyContext();
        }

        return context;
    }

    private SecurityContext readSecurityContext(int tokenType, String userdata) {
        AccountAuthToken authToken = accountTokenService.getAuthToken(tokenType, userdata);
        if (authToken != null) {
            SecurityContext context = SecurityContextHolder.createEmptyContext();
            context.setAuthentication(authToken);
            return context;
        } else {
            if (tokenType == TokenType.cookie.getValue()) {
                // 没有认证信息时重置 response 中返回的 cookie
                accountTokenService.clearCookie();
            }
            return null;
        }
    }

    @Override
    public void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response) {
    }

    @Override
    public boolean containsContext(HttpServletRequest request) {
        return false;
    }
}
