package tech.easyflow.approval.service.impl;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import tech.easyflow.approval.entity.ApprovalFlow;
import tech.easyflow.approval.entity.vo.ApprovalAssigneeTargetVo;
import tech.easyflow.approval.entity.vo.ApprovalFlowDetailVo;
import tech.easyflow.approval.entity.vo.ApprovalFlowStepVo;
import tech.easyflow.approval.enums.ApprovalAssigneeType;
import tech.easyflow.approval.mapper.ApprovalFlowMapper;
import tech.easyflow.approval.mapper.ApprovalFlowScopeMapper;
import tech.easyflow.approval.mapper.ApprovalFlowStepMapper;
import tech.easyflow.approval.mapper.ApprovalInstanceMapper;
import tech.easyflow.approval.service.ApprovalAssigneeService;

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

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.verify;

/**
 * {@link ApprovalFlowServiceImpl} 流程配置校验测试。
 */
@RunWith(MockitoJUnitRunner.class)
public class ApprovalFlowServiceImplTest {

    @Mock
    private ApprovalFlowMapper approvalFlowMapper;

    @Mock
    private ApprovalFlowScopeMapper approvalFlowScopeMapper;

    @Mock
    private ApprovalFlowStepMapper approvalFlowStepMapper;

    @Mock
    private ApprovalInstanceMapper approvalInstanceMapper;

    @Mock
    private ApprovalAssigneeService approvalAssigneeService;

    @InjectMocks
    private ApprovalFlowServiceImpl service;

    /**
     * 验证受限步骤在写入流程前完成合法候选账号校验。
     */
    @Test
    public void saveFlowShouldValidateRestrictedCandidatesBeforeInsert() {
        ApprovalFlowStepVo step = new ApprovalFlowStepVo();
        step.setStepName("审核");
        step.setAssigneeType(ApprovalAssigneeType.USER.getCode());
        step.setRestrictToApplicantDept(1);
        ApprovalAssigneeTargetVo target = new ApprovalAssigneeTargetVo();
        target.setTargetId(BigInteger.valueOf(11));
        step.setAssigneeTargets(List.of(target));

        ApprovalFlowDetailVo request = new ApprovalFlowDetailVo();
        request.setName("发布审批");
        request.setResourceType("WORKFLOW");
        request.setActionType("PUBLISH");
        request.setPriority(100);
        request.setStatus("ENABLED");
        request.setSteps(List.of(step));
        doAnswer(invocation -> invocation.getArgument(0))
                .when(approvalAssigneeService)
                .normalizeStepAssignee(any(ApprovalFlowStepVo.class));
        doAnswer(invocation -> {
            ((ApprovalFlow) invocation.getArgument(0)).setId(BigInteger.valueOf(301));
            return 1;
        }).when(approvalFlowMapper).insert(any(ApprovalFlow.class));

        assertEquals(BigInteger.valueOf(301),
                service.saveFlow(request, BigInteger.valueOf(7)));

        InOrder order = inOrder(approvalAssigneeService, approvalFlowMapper);
        order.verify(approvalAssigneeService)
                .validateRestrictedStepCandidates(any(), isNull());
        order.verify(approvalFlowMapper).insert(any(ApprovalFlow.class));
        verify(approvalAssigneeService).saveStepAssigneeTargets(
                any(), any(), any(), any(), any());
    }
}
