package cn.reghao.bnt.web.admin.service;

import cn.reghao.bnt.web.admin.db.repository.LoginAttemptsRepository;
import cn.reghao.bnt.web.admin.model.po.LoginAttempt;
import cn.reghao.bnt.web.admin.model.po.User;
import cn.reghao.bnt.web.admin.model.vo.UserSession;
import cn.reghao.jutil.jdk.converter.DateTimeConverter;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.session.Session;
import org.springframework.session.jdbc.JdbcIndexedSessionRepository;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

/**
 * @author reghao
 * @date 2024-02-04 16:00:01
 */
@Service
public class AccountSessionService {
    private final SessionRegistry sessionRegistry;
    private final JdbcIndexedSessionRepository sessionRepository;
    private final AccountService accountService;
    private final LoginAttemptsRepository loginAttemptsRepository;

    public AccountSessionService(SessionRegistry sessionRegistry, JdbcIndexedSessionRepository sessionRepository,
                                 AccountService accountService,LoginAttemptsRepository loginAttemptsRepository) {
        this.sessionRegistry = sessionRegistry;
        this.sessionRepository = sessionRepository;
        this.accountService = accountService;
        this.loginAttemptsRepository = loginAttemptsRepository;
    }

    public Map<Integer, String> getLastAccess() {
        Map<Integer, String> map = new HashMap<>();
        for (Object principal : sessionRegistry.getAllPrincipals()) {
            int userId = (int) principal;
            User user = accountService.getById(userId);
            for (SessionInformation sessionInfo : sessionRegistry.getAllSessions(principal, false)) {
                Date date = sessionInfo.getLastRequest();
                LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
                String localDateTimeStr = DateTimeConverter.format(localDateTime);
                map.put(user.getId(), localDateTimeStr);
            }
        }

        return map;
    }

    public List<UserSession>  getUserSession(int userId) {
        /*String sessionId = ServletUtil.getSessionId();
        Session session = sessionRepository.findById(sessionId);
        Object object = session.getAttribute("SPRING_SECURITY_CONTEXT");
        if (object instanceof SecurityContext) {
            SecurityContext securityContext = (SecurityContext) object;
            AccountAuthToken authToken = (AccountAuthToken) securityContext.getAuthentication();
            int userId = (int) authToken.getPrincipal();
            String principalName = "" + userId;
            sessionRepository.findByPrincipalName(principalName);
            List<SessionInformation> list = sessionRegistry.getAllSessions(principalName, false);
        }*/

        List<UserSession> userSessionList = new ArrayList<>();
        String principalName = "" + userId;
        List<SessionInformation> list = sessionRegistry.getAllSessions(principalName, false);
        for (SessionInformation sessionInformation : list) {
            String sessionId = sessionInformation.getSessionId();
            Session springSession = sessionRepository.findById(sessionId);
            Instant createInstant = springSession.getCreationTime();
            LocalDateTime createDateTime = LocalDateTime.ofInstant(createInstant, ZoneId.systemDefault());

            Date lastRequest = sessionInformation.getLastRequest();
            LocalDateTime lastDateTime = LocalDateTime.ofInstant(lastRequest.toInstant(), ZoneId.systemDefault());
            UserSession userSession = new UserSession(userId, sessionId, createDateTime, lastDateTime);
            LoginAttempt loginAttempt = loginAttemptsRepository.findByLoginId(sessionId);
            if (loginAttempt != null) {
                String userAgent = loginAttempt.getUserAgent();
                String loginIp = loginAttempt.getLoginIp();
                userSession.setUserAgent(userAgent);
                userSession.setLoginIp(loginIp);
            }
            userSessionList.add(userSession);
        }

        return userSessionList;
    }

    public List<String> getActiveLoginIds(int userId) {
        List<String> activeSessionIds = new ArrayList<>();
        String principalName = "" + userId;
        List<SessionInformation> list = sessionRegistry.getAllSessions(principalName, false);
        for (SessionInformation sessionInformation : list) {
            String sessionId = sessionInformation.getSessionId();
            activeSessionIds.add(sessionId);
        }

        return activeSessionIds;
    }

    /**
     * 登出用户的某个 session
     *
     * @param
     * @return
     * @date 2025-10-02 01:10:674
     */
    public void deactivateUserLogin(String loginId) {
        String sessionId = loginId;
        Session springSession = sessionRepository.findById(sessionId);
        if (springSession != null && !springSession.isExpired()) {
            sessionRepository.deleteById(sessionId);
        }
    }

    /**
     * 登出用户的所有 session
     *
     * @param
     * @return
     * @date 2025-10-02 01:10:381
     */
    public void deactivateUserSession(int userId) {
        String principalName = "" + userId;
        List<SessionInformation> list = sessionRegistry.getAllSessions(principalName, false);
        for (SessionInformation sessionInformation : list) {
            String sessionId = sessionInformation.getSessionId();
            deactivateUserLogin(sessionId);
        }
    }
}
