package com.hz.pm.api.user.manage;

import com.hz.pm.api.common.helper.UserInfoHelper;
import com.hz.pm.api.user.convert.UserInfoConvertor;
import com.hz.pm.api.user.security.auth.credential.CredentialAuthToken;
import com.hz.pm.api.user.security.model.UserFullInfoDTO;
import com.hz.pm.api.user.security.model.UserInfoDetails;
import lombok.AllArgsConstructor;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.session.Session;
import org.springframework.session.SessionRepository;
import org.springframework.session.data.redis.RedisIndexedSessionRepository;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * UserAuthHelper
 * </p>
 *
 * @author WendyYang
 * @since 2023/5/5
 **/
@Component
@AllArgsConstructor
public class UserAuthManage {

    private final UserInfoHelper userInfoHelper;
    private final RedisIndexedSessionRepository redisSessionRepository;

    @SuppressWarnings({"rawtypes", "unchecked"})
    public void refreshSession(Long userId) {
        UserFullInfoDTO userFullInfo = userInfoHelper.getUserFullInfo(userId);
        if (userFullInfo == null) {
            return;
        }
        List<String> sessionIds = getSessionIds(userFullInfo.getUsername());
        if (sessionIds.isEmpty()) {
            return;
        }
        SessionRepository sessionRepository = redisSessionRepository;
        UserInfoDetails details = UserInfoConvertor.convert(userFullInfo);
        CredentialAuthToken cat = new CredentialAuthToken(details, details.getPassword(), details.getAuthorities());
        sessionIds.forEach(sessionId -> {
            Session session = redisSessionRepository.findById(sessionId);
            SecurityContextImpl context = session.getAttribute("SPRING_SECURITY_CONTEXT");
            context.setAuthentication(cat);
            session.setAttribute("SPRING_SECURITY_CONTEXT", context);
            sessionRepository.save(session);
        });
    }

    private List<String> getSessionIds(String username) {
        return new ArrayList<>(redisSessionRepository.findByPrincipalName(username).keySet());
    }

    public void kickOff(Long userId) {
        UserFullInfoDTO userFullInfo = userInfoHelper.getUserFullInfo(userId);
        List<String> sessionIds = getSessionIds(userFullInfo.getUsername());
        sessionIds.forEach(redisSessionRepository::deleteById);
    }

}
