package tech.easyflow.ai.service.impl;

import com.mybatisflex.core.query.QueryWrapper;
import org.junit.Assert;
import org.junit.Test;
import tech.easyflow.common.web.exceptions.BusinessException;
import tech.easyflow.system.entity.SysApiKey;
import tech.easyflow.system.entity.SysApiKeyResource;
import tech.easyflow.system.service.SysApiKeyResourceMappingService;
import tech.easyflow.system.service.SysApiKeyResourceService;
import tech.easyflow.system.service.SysApiKeyService;

import java.lang.reflect.Field;
import java.math.BigInteger;

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

/**
 * {@link WorkflowApiPermissionServiceImpl} 权限错误语义测试。
 */
public class WorkflowApiPermissionServiceImplTest {

    /**
     * 验证未开启工作流 API 授权时返回 HTTP 403。
     *
     * @throws Exception 测试依赖注入失败时抛出
     */
    @Test
    public void shouldReturnForbiddenWhenWorkflowApiPermissionMissing()
            throws Exception {
        SysApiKeyService apiKeyService = mock(SysApiKeyService.class);
        SysApiKeyResourceService resourceService =
                mock(SysApiKeyResourceService.class);
        SysApiKeyResourceMappingService mappingService =
                mock(SysApiKeyResourceMappingService.class);
        SysApiKey apiKey = new SysApiKey();
        apiKey.setId(BigInteger.ONE);
        SysApiKeyResource resource = new SysApiKeyResource();
        resource.setId(BigInteger.TWO);
        when(apiKeyService.getSysApiKey("test-key")).thenReturn(apiKey);
        when(resourceService.getOne(any(QueryWrapper.class)))
                .thenReturn(resource);
        when(mappingService.count(any(QueryWrapper.class))).thenReturn(0L);
        WorkflowApiPermissionServiceImpl service =
                new WorkflowApiPermissionServiceImpl();
        setField(service, "sysApiKeyService", apiKeyService);
        setField(service, "resourceService", resourceService);
        setField(service, "mappingService", mappingService);

        try {
            service.assertWorkflowApi(
                    "test-key",
                    "/public-api/workflow/runAsync");
            Assert.fail("expected BusinessException");
        } catch (BusinessException error) {
            Assert.assertEquals(403, error.getHttpStatus());
            Assert.assertEquals(403, error.getErrorCode());
        }
    }

    /**
     * 注入测试依赖。
     *
     * @param target 目标对象
     * @param name 字段名
     * @param value 字段值
     * @throws Exception 反射访问失败时抛出
     */
    private void setField(Object target, String name, Object value)
            throws Exception {
        Field field = target.getClass().getDeclaredField(name);
        field.setAccessible(true);
        field.set(target, value);
    }
}
