package com.ningdatech.kqapi.security.listener;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.ningdatech.kqapi.security.model.UserInfoDetails;
import com.ningdatech.kqapi.security.model.WebRequestDetails;
import com.ningdatech.log.model.OptLogDTO;
import com.ningdatech.log.model.enumeration.LogType;
import com.ningdatech.log.service.OptLogService;
import com.ningdatech.log.util.AddressUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.authentication.event.AbstractAuthenticationEvent;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.security.authentication.event.LogoutSuccessEvent;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

/**
 * <p>
 * AuthEventListener
 * </p>
 *
 * @author WendyYang
 * @since 11:27 2024/4/20
 */
@Component
@RequiredArgsConstructor
public class AuthEventListener {

    private final OptLogService optLogService;

    private static final String LOGIN = "用户登录";

    private static final String LOGOUT = "退出登录";

    @Async
    @EventListener(AuthenticationSuccessEvent.class)
    public void loginSuccessListener(AuthenticationSuccessEvent event) {
        OptLogDTO optLog = buildOptLog(LOGIN, event);
        optLogService.save(optLog);
    }

    @Async
    @EventListener(LogoutSuccessEvent.class)
    public void logoutSuccessListener(LogoutSuccessEvent event) {
        OptLogDTO optLog = buildOptLog(LOGOUT, event);
        optLogService.save(optLog);
    }

    private OptLogDTO buildOptLog(String description, AbstractAuthenticationEvent event) {
        Authentication authentication = event.getAuthentication();
        UserInfoDetails userDetails = (UserInfoDetails) authentication.getPrincipal();
        WebRequestDetails webDetails = (WebRequestDetails) authentication.getDetails();
        OptLogDTO optLog = new OptLogDTO();
        optLog.setActionMethod(webDetails.getServletPath());
        optLog.setDescription(description);
        if (event instanceof AuthenticationSuccessEvent) {
            optLog.setStartTime(webDetails.getLoginTime());
        } else {
            optLog.setStartTime(LocalDateTimeUtil.of(event.getTimestamp()));
        }
        LocalDateTime now = LocalDateTime.now();
        optLog.setFinishTime(now);
        optLog.setCreateOn(now);
        long consumingTime = ChronoUnit.MILLIS.between(optLog.getStartTime(), now);
        optLog.setConsumingTime(consumingTime);
        optLog.setHttpMethod(webDetails.getMethod());
        optLog.setUserName(userDetails.getRealName());
        optLog.setCreateBy(userDetails.getUserId());
        optLog.setRequestIp(webDetails.getRequestIp());
        optLog.setRequestUri(webDetails.getRequestUri());
        optLog.setRegionByIp(AddressUtil.getRegion(optLog.getRequestIp()));
        optLog.setUa(webDetails.getUserAgent());
        optLog.setType(LogType.OPT.name());
        return optLog;
    }

}