package com.nailart.aop;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.nailart.dto.RequestLogDTO;
import com.nailart.utils.IpAddressUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import jakarta.servlet.http.HttpServletRequest;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

/**
 * @Description 实现日志记录
 * @Classname RequestLogDTOAspect
 * @Date 2025/7/11 0:05
 * @Created by 21616
 */
@Aspect
@Component
public class RequestLogAspect {
    @Autowired
    private IpAddressUtil ipAddressUtil;

    private final ObjectMapper objectMapper = new ObjectMapper();
    private final String logFilePath = "request_logs.json"; // 日志文件路径

    @Pointcut("execution(* com.nailart.controller..*(..))")
    public void requestPointcut() {}

    @Around("requestPointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) {
            return joinPoint.proceed();
        }
        HttpServletRequest request = attributes.getRequest();

        RequestLogDTO log = new RequestLogDTO();
        log.setRequestTime(new Date());
        log.setIp(getClientIp(request));
        log.setCity(ipAddressUtil.getCityInfo(log.getIp()));
        log.setUrl(request.getRequestURL().toString());
        log.setHttpMethod(request.getMethod());
        log.setMethod(joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());

        try {
            return joinPoint.proceed();
        } finally {
            log.setResponseTime(System.currentTimeMillis() - startTime);
            // 直接将日志写入文件，不使用日志框架
            writeLogToFile(log);
        }
    }

    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }
        return ip;
    }

    private void writeLogToFile(RequestLogDTO log) {
        try (PrintWriter writer = new PrintWriter(new FileWriter(logFilePath, true))) {
            // 将日志对象序列化为JSON并写入文件
            writer.println(objectMapper.writeValueAsString(log));
        } catch (IOException e) {
            // 处理写入异常（可以选择记录到标准输出或忽略）
            System.err.println("Failed to write request log: " + e.getMessage());
        }
    }
}