package com.cf.imes.module.system.common;

import com.cf.imes.framework.security.core.LoginUser;
import com.cf.imes.framework.security.test.WithMockLoginUser;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.mockito.Mockito;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;

/**
 *
 *
 * @author Gqr
 * @since 2026/1/16 10:20
 */
@Slf4j
public class WithMockLoginUserExtension implements BeforeEachCallback, AfterEachCallback {
    @Override
    public void afterEach(ExtensionContext context) {
        SecurityContextHolder.clearContext();
    }

    @Override
    public void beforeEach(ExtensionContext context) {
        WithMockLoginUser ann = findAnnotation(context);

        LoginUser loginUser = new LoginUser();
        if (ann != null) {
            loginUser.setId(ann.userId());
            loginUser.setOrganId(ann.organId());
            loginUser.setDeptId(ann.deptId());
            loginUser.setNickname(ann.username());
            loginUser.setIsSupAdmin(ann.isSuperAdmin());
            loginUser.setUserType(ann.userType());
            loginUser.setProductId(ann.productId());
        } else {
            return;
        }

        Authentication authentication = Mockito.mock(Authentication.class);
        Mockito.when(authentication.getPrincipal()).thenReturn(loginUser);

        SecurityContext securityContext = Mockito.mock(SecurityContext.class);
        Mockito.when(securityContext.getAuthentication())
                .thenReturn(authentication);

        SecurityContextHolder.setContext(securityContext);
    }

    private WithMockLoginUser findAnnotation(ExtensionContext context) {
        return context.getElement()
                .map(el -> el.getAnnotation(WithMockLoginUser.class))
                .orElse(null);
    }
}
