package cn.axzo.workflow.server.controller.web.bpmn;

import cn.axzo.workflow.client.feign.bpmn.ProcessActivityApi;
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutCallbackDTO;
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutTriggerDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivitySetAssigneeDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivityTriggerDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.common.exception.WorkflowEngineException;
import cn.axzo.workflow.core.service.BpmnProcessActivityService;
import cn.axzo.workflow.server.common.annotation.ErrorReporter;
import cn.axzo.workflow.server.common.annotation.RepeatSubmit;
import cn.axzo.workflow.server.controller.web.BasicPopulateAvatarController;
import cn.azxo.framework.common.model.CommonResponse;
import com.alibaba.fastjson.JSON;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.constraints.NotBlank;
import java.util.ArrayList;
import java.util.List;

import static cn.axzo.workflow.common.code.BpmnTaskRespCode.ACTIVITY_BIZ_SET_ASSIGNEE_HAS_REPEAT;
import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.removeDuplicateByPersonId;
import static cn.azxo.framework.common.model.CommonResponse.success;

/**
 * 流程活动相关控制器
 *
 * @author wangli
 * @since 2023/11/17 16:33
 */
@Slf4j
@RequestMapping({"/web/v1/api/process/activity", "/api/process/activity"})
@RestController
@ErrorReporter
@Validated
public class BpmnProcessActivityController extends BasicPopulateAvatarController implements ProcessActivityApi {

    @Resource
    private BpmnProcessActivityService bpmnProcessActivityService;

    /**
     * 业务节点唤醒
     * 旧版本使用的接口, 建议使用 {@link BpmnProcessActivityController#trigger(BpmnActivityTriggerDTO)}
     *
     * @param triggerId
     * @return
     */
    @Operation(summary = "业务节点唤醒")
    @GetMapping("/trigger")
    @Override
    @RepeatSubmit
    @Deprecated
    public CommonResponse<Boolean> trigger(@NotBlank(message = "触发 ID 不能为空") @RequestParam String triggerId) {
        log.info("业务节点唤醒 trigger2 ===>>>参数：{}", triggerId);
        return trigger(new BpmnActivityTriggerDTO(triggerId, true, null));
    }

    /**
     * 业务节点唤醒
     *
     * @param dto
     * @return
     */
    @Operation(summary = "业务节点唤醒")
    @PostMapping("/trigger")
    @Override
    @RepeatSubmit
    public CommonResponse<Boolean> trigger(@Validated @RequestBody BpmnActivityTriggerDTO dto) {
        log.info("业务节点唤醒 trigger ===>>>参数：{}", JSON.toJSONString(dto));
        bpmnProcessActivityService.trigger(dto);
        return success(true);
    }

    /**
     * 业务节点设置审批人
     * <p>
     * 不支持重复调用设置审批人，需一次性传入所有审批人
     *
     * @param dto
     * @return
     */
    @Operation(summary = "业务节点设置审批人")
    @PostMapping("/assignee/set")
    @Override
    @RepeatSubmit
    public CommonResponse<Boolean> setAssignee(@Validated @RequestBody BpmnActivitySetAssigneeDTO dto) {
        log.info("业务节点设置审批人 setAssignee ===>>>参数：{}", JSON.toJSONString(dto));
        if (!dto.getServerSideDeduplication()) {
            List<String> personIds = new ArrayList<>();
            for (BpmnTaskDelegateAssigner assigner : dto.getAssigners()) {
                if (personIds.contains(assigner.getPersonId())) {
                    throw new WorkflowEngineException(ACTIVITY_BIZ_SET_ASSIGNEE_HAS_REPEAT);
                }
                personIds.add(assigner.getPersonId());
            }
        } else {
            dto.setAssigners(removeDuplicateByPersonId(dto.getAssigners()));
        }

        //填充头像
        populateUsersAvatar(dto.getAssigners());

        bpmnProcessActivityService.setAssignee(dto);
        return success(true);
    }

    /**
     * 该功能应该利用引擎的 TimerBoundaryEvent 来实现，但为了简便，先利用引擎的任务调度来实现
     *
     * @param dto
     * @return
     */
    @PostMapping("/timeout/trigger")
    @Override
    public CommonResponse<Boolean> setTimeoutTrigger(@Validated @RequestBody BpmnActivityTimeoutTriggerDTO dto) {
        log.info("倒计时触发 setTimeoutTrigger ===>>>参数：{}", JSON.toJSONString(dto));
        return CommonResponse.success(bpmnProcessActivityService.setTimeoutTrigger(dto));
    }

    /**
     * 为指定业务节点设置定时回调
     *
     * @param dto
     * @return
     */
    @PostMapping("/timeout/callback")
    @Override
    public CommonResponse<Boolean> setTimeoutCallback(@Validated @RequestBody BpmnActivityTimeoutCallbackDTO dto) {
        log.info("倒计时回调 setTimeoutCallback ===>>>参数：{}", JSON.toJSONString(dto));
        return CommonResponse.success(bpmnProcessActivityService.setTimeOutCallback(dto));
    }
}
