package tech.easyflow.admin.controller.ai;

import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import tech.easyflow.admin.controller.ai.support.AiResourceCreatorNameSupport;
import tech.easyflow.ai.entity.Bot;
import tech.easyflow.ai.service.AiResourceApprovalStateService;
import tech.easyflow.ai.service.BotDocumentCollectionService;
import tech.easyflow.ai.service.BotMessageService;
import tech.easyflow.ai.service.BotService;
import tech.easyflow.ai.service.BotWorkflowService;
import tech.easyflow.ai.service.ModelService;
import tech.easyflow.system.entity.vo.RoleCategoryAccessSnapshot;
import tech.easyflow.system.service.CategoryPermissionService;
import tech.easyflow.system.service.SysAccountService;

import java.math.BigInteger;
import java.util.Collections;
import java.util.Map;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

/**
 * {@link BotController} 测试。
 */
public class BotControllerTest {

    private BotService botService;
    private ModelService modelService;
    private BotWorkflowService botWorkflowService;
    private BotDocumentCollectionService botDocumentCollectionService;
    private BotMessageService botMessageService;
    private CategoryPermissionService categoryPermissionService;
    private AiResourceApprovalStateService aiResourceApprovalStateService;
    private SysAccountService sysAccountService;

    /**
     * 初始化测试 mock。
     */
    @BeforeMethod
    public void setUp() {
        botService = mock(BotService.class);
        modelService = mock(ModelService.class);
        botWorkflowService = mock(BotWorkflowService.class);
        botDocumentCollectionService = mock(BotDocumentCollectionService.class);
        botMessageService = mock(BotMessageService.class);
        categoryPermissionService = mock(CategoryPermissionService.class);
        aiResourceApprovalStateService = mock(AiResourceApprovalStateService.class);
        sysAccountService = mock(SysAccountService.class);
    }

    /**
     * 验证分页结果会补充创建人展示名称，且只做一次批量账号查询。
     */
    @Test
    public void shouldFillCreatedByNameForPageRecords() {
        TestBotController controller = new TestBotController(
                botService,
                modelService,
                botWorkflowService,
                botDocumentCollectionService,
                botMessageService
        );
        AiResourceCreatorNameSupport creatorNameSupport = new AiResourceCreatorNameSupport();
        setField(creatorNameSupport, "sysAccountService", sysAccountService);
        setField(controller, "categoryPermissionService", categoryPermissionService);
        setField(controller, "aiResourceApprovalStateService", aiResourceApprovalStateService);
        setField(controller, "aiResourceCreatorNameSupport", creatorNameSupport);

        Bot bot = new Bot();
        bot.setId(BigInteger.valueOf(101));
        bot.setCreatedBy(BigInteger.valueOf(7));
        Page<Bot> page = new Page<>(Collections.singletonList(bot), 1, 10, 1);

        when(categoryPermissionService.getCurrentAccess("BOT"))
                .thenReturn(new RoleCategoryAccessSnapshot("BOT", BigInteger.ONE, false, true, Collections.emptySet()));
        when(botService.page(any(Page.class), any(QueryWrapper.class))).thenReturn(page);
        when(sysAccountService.resolveDisplayNameMap(Collections.singleton(BigInteger.valueOf(7))))
                .thenReturn(Map.of(BigInteger.valueOf(7), "管理员"));
        doNothing().when(aiResourceApprovalStateService).fillBotApprovalState(page.getRecords());

        Page<Bot> result = controller.invokeQueryPage(new Page<>(1, 10), QueryWrapper.create());

        Assert.assertEquals(result.getRecords().get(0).getCreatedByName(), "管理员");
        verify(sysAccountService).resolveDisplayNameMap(Collections.singleton(BigInteger.valueOf(7)));
    }

    /**
     * 通过反射设置字段值。
     *
     * @param target    目标对象
     * @param fieldName 字段名
     * @param value     字段值
     */
    private static void setField(Object target, String fieldName, Object value) {
        Class<?> current = target.getClass();
        while (current != null) {
            try {
                java.lang.reflect.Field field = current.getDeclaredField(fieldName);
                field.setAccessible(true);
                field.set(target, value);
                return;
            } catch (NoSuchFieldException ignored) {
                current = current.getSuperclass();
            } catch (IllegalAccessException e) {
                throw new IllegalStateException("设置测试字段失败: " + fieldName, e);
            }
        }
        throw new IllegalArgumentException("未找到字段: " + fieldName);
    }

    /**
     * 暴露受保护分页方法的测试控制器。
     */
    private static class TestBotController extends BotController {

        TestBotController(
                BotService service,
                ModelService modelService,
                BotWorkflowService botWorkflowService,
                BotDocumentCollectionService botDocumentCollectionService,
                BotMessageService botMessageService
        ) {
            super(service, modelService, botWorkflowService, botDocumentCollectionService, botMessageService);
        }

        /**
         * 调用受保护的分页查询方法。
         *
         * @param page         分页对象
         * @param queryWrapper 查询条件
         * @return 查询结果
         */
        Page<Bot> invokeQueryPage(Page<Bot> page, QueryWrapper queryWrapper) {
            return super.queryPage(page, queryWrapper);
        }
    }
}
