package dev.lions.user.manager.server.impl.interceptor;

import dev.lions.user.manager.dto.audit.AuditLogDTO;
import dev.lions.user.manager.enums.audit.TypeActionAudit;
import dev.lions.user.manager.service.AuditService;
import io.quarkus.security.identity.SecurityIdentity;
import jakarta.annotation.Priority;
import jakarta.inject.Inject;
import jakarta.interceptor.AroundInvoke;
import jakarta.interceptor.Interceptor;
import jakarta.interceptor.InvocationContext;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;

@Logged
@Interceptor
@Priority(Interceptor.Priority.APPLICATION)
@Slf4j
public class AuditInterceptor {

    @Inject
    AuditService auditService;

    @Inject
    SecurityIdentity securityIdentity;

    @AroundInvoke
    public Object auditMethod(InvocationContext context) throws Exception {
        Logged annotation = context.getMethod().getAnnotation(Logged.class);
        if (annotation == null) {
            annotation = context.getTarget().getClass().getAnnotation(Logged.class);
        }

        String actionStr = annotation != null ? annotation.action() : "UNKNOWN";
        String resourceType = annotation != null ? annotation.resource() : "UNKNOWN";
        String username = securityIdentity.isAnonymous() ? "anonymous" : securityIdentity.getPrincipal().getName();

        // Extraction du realm depuis l'issuer JWT (ex: http://keycloak/realms/lions-user-manager)
        String realmName = "unknown";
        if (!securityIdentity.isAnonymous()
                && securityIdentity.getPrincipal() instanceof org.eclipse.microprofile.jwt.JsonWebToken jwt) {
            String issuer = jwt.getIssuer();
            if (issuer != null && issuer.contains("/realms/")) {
                realmName = issuer.substring(issuer.lastIndexOf("/realms/") + 8);
            }
        }

        // Tentative d'extraction de l'ID de la ressource (1er argument String)
        String resourceId = "";
        if (context.getParameters().length > 0 && context.getParameters()[0] instanceof String) {
            resourceId = (String) context.getParameters()[0];
        }

        try {
            Object result = context.proceed();

            // Log Success
            try {
                TypeActionAudit action = TypeActionAudit.valueOf(actionStr);
                auditService.logSuccess(
                        action,
                        resourceType,
                        resourceId,
                        null,
                        realmName,
                        username,
                        "Action réussie via AOP");
            } catch (IllegalArgumentException e) {
                log.warn("Type d'action audit inconnu: {}", actionStr);
            }

            return result;
        } catch (Exception e) {
            // Log Failure
            try {
                TypeActionAudit action = TypeActionAudit.valueOf(actionStr);
                auditService.logFailure(
                        action,
                        resourceType,
                        resourceId,
                        null,
                        realmName,
                        username,
                        "ERROR",
                        e.getMessage());
            } catch (IllegalArgumentException ex) {
                log.warn("Type d'action audit inconnu: {}", actionStr);
            }
            throw e;
        }
    }
}
