package com.oguerreiro.resilient.security.custom;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Aspect
@Component
@Order(1)   // Needed to guarantee that it runs BEFORE spring security @PreAuthorize evaluation
public class ResilientSecurityContextAspect {

  private static final ThreadLocal<ResilientSecurityContext> currentTargetInstance = new ThreadLocal<>();

  // Inject needed info into a ThreadLocal variable
  @Before("execution(@org.springframework.security.access.prepost.PreAuthorize * *.*(..))")
  public void captureTargetInstance(org.aspectj.lang.JoinPoint joinPoint) {
    Object target = joinPoint.getTarget();  // Get the class instance where the method is being called

    currentTargetInstance.set(
        new ResilientSecurityContext(target, joinPoint.getSignature().getName(), joinPoint.getArgs()));      // Store the instance in ThreadLocal
  }

  // Clear the ThreadLocal variable, for safety
  @After("execution(@org.springframework.security.access.prepost.PreAuthorize * *.*(..))")
  public void clearTargetInstance() {
    currentTargetInstance.remove();  // Clean up after method execution
  }

  public static ResilientSecurityContext getCurrentTargetInstance() {
    return currentTargetInstance.get();    // Retrieve the stored instance
  }

  public static void clear() {
    currentTargetInstance.remove();        // Clear the stored instance after the request is processed
  }
}
