package tech.easyflow.agent.runtime.hitl;

import com.mybatisflex.core.query.QueryWrapper;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
import tech.easyflow.agent.config.AgentRuntimeProperties;
import tech.easyflow.agent.entity.AgentHitlPending;
import tech.easyflow.agent.mapper.AgentHitlPendingMapper;

import java.math.BigInteger;
import java.util.List;

/**
 * {@link AgentHitlPendingServiceImpl} 回归测试。
 */
public class AgentHitlPendingServiceImplTest {

    /**
     * 验证过期扫描只返回成功从 PENDING 原子更新为 EXPIRED 的记录。
     */
    @Test
    public void expirePendingShouldIgnoreConcurrentlyConsumedRecord() {
        AgentHitlPendingMapper mapper = Mockito.mock(AgentHitlPendingMapper.class);
        AgentHitlPending first = pending(BigInteger.ONE, "request-1", "token-1");
        AgentHitlPending concurrentlyApproved = pending(BigInteger.TWO, "request-2", "token-2");
        Mockito.when(mapper.selectListByQuery(Mockito.any(QueryWrapper.class)))
                .thenReturn(List.of(first, concurrentlyApproved));
        Mockito.when(mapper.updateByQuery(
                        Mockito.any(AgentHitlPending.class), Mockito.any(QueryWrapper.class)))
                .thenReturn(1, 0);
        AgentHitlPendingServiceImpl service =
                new AgentHitlPendingServiceImpl(mapper, new AgentRuntimeProperties());

        List<AgentHitlPending> expired = service.expirePending(100);

        Assert.assertEquals(1, expired.size());
        Assert.assertSame(first, expired.get(0));
        Assert.assertEquals(AgentHitlPendingStatus.EXPIRED.name(), first.getStatus());
        Assert.assertEquals(AgentHitlPendingStatus.PENDING.name(), concurrentlyApproved.getStatus());
        Mockito.verify(mapper, Mockito.times(2)).updateByQuery(
                Mockito.any(AgentHitlPending.class), Mockito.any(QueryWrapper.class));
    }

    /**
     * 创建待过期审批记录。
     *
     * @param id 记录 ID
     * @param requestId 请求 ID
     * @param resumeToken 恢复令牌
     * @return 审批记录
     */
    private AgentHitlPending pending(BigInteger id, String requestId, String resumeToken) {
        AgentHitlPending pending = new AgentHitlPending();
        pending.setId(id);
        pending.setRequestId(requestId);
        pending.setResumeToken(resumeToken);
        pending.setStatus(AgentHitlPendingStatus.PENDING.name());
        pending.setIsDeleted(0);
        return pending;
    }
}
