package com.qqchen.deploy.backend.framework.audit.aspect;

import com.qqchen.deploy.backend.framework.audit.AuditMetadata;
import com.qqchen.deploy.backend.framework.annotation.Audited;
import com.qqchen.deploy.backend.framework.audit.event.AuditEvent;
import com.qqchen.deploy.backend.framework.security.SecurityUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.time.LocalDateTime;

@Aspect
@Component
@Slf4j
@RequiredArgsConstructor
public class AuditAspect {

    private final ApplicationEventPublisher eventPublisher;

    @Around("@annotation(com.qqchen.deploy.backend.framework.annotation.Audited)")
    public Object auditMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取审计元数据
        AuditMetadata metadata = extractAuditMetadata(joinPoint);
        
        try {
            // 执行原方法
            Object result = joinPoint.proceed();
            
            // 发布审计事件
            eventPublisher.publishEvent(new AuditEvent(this, metadata));
            
            return result;
        } catch (Exception e) {
            // 记录异常信息
            metadata.setDetail(metadata.getDetail() + " [Error: " + e.getMessage() + "]");
            eventPublisher.publishEvent(new AuditEvent(this, metadata));
            throw e;
        }
    }

    private AuditMetadata extractAuditMetadata(ProceedingJoinPoint joinPoint) {
        AuditMetadata metadata = new AuditMetadata();
        
        // 设置基本信息
        metadata.setOperator(SecurityUtils.getCurrentUsername());
        metadata.setTimestamp(LocalDateTime.now());
//        metadata.setTenantId(SecurityUtils.getCurrentTenantId());
        
        // 设置IP地址
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
            .getRequestAttributes()).getRequest();
        metadata.setIp(getClientIp(request));
        
        // 获取方法上的注解信息
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Audited audited = signature.getMethod().getAnnotation(Audited.class);
        
        metadata.setAction(audited.action());
        metadata.setDetail(audited.detail());
        
        // 设置实体信息
        String className = joinPoint.getTarget().getClass().getSimpleName();
        metadata.setEntityType(className.replace("ServiceImpl", ""));
        
        return metadata;
    }

    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();
        }
        return ip;
    }
} 