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

import cn.axzo.workflow.client.feign.bpmn.ProcessModelApi;
import cn.axzo.workflow.common.model.request.bpmn.model.BpmnModelCreateDTO;
import cn.axzo.workflow.common.model.request.bpmn.model.BpmnModelSearchDTO;
import cn.axzo.workflow.common.model.request.bpmn.model.BpmnModelUpdateDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.common.model.response.BpmPageResult;
import cn.axzo.workflow.common.model.response.bpmn.model.BpmnModelDetailVO;
import cn.axzo.workflow.common.model.response.bpmn.model.BpmnModelExtVO;
import cn.axzo.workflow.core.service.BpmnProcessModelService;
import cn.axzo.workflow.core.service.ExtAxReModelService;
import cn.axzo.workflow.server.common.annotation.ErrorReporter;
import cn.axzo.workflow.server.common.annotation.RepeatSubmit;
import cn.azxo.framework.common.model.CommonResponse;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
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 javax.validation.constraints.NotNull;
import java.util.List;

import static cn.azxo.framework.common.model.CommonResponse.success;

/**
 * 流程模型相关控制器
 */
@Tag(name = "运维管理 - 流程模型")
@Slf4j
@RequestMapping({"/web/v1/api/process/model", "/api/process/model"})
@RestController
@ErrorReporter
@Validated
public class BpmnProcessModelController implements ProcessModelApi {

    @Resource
    private BpmnProcessModelService bpmnProcessModelService;
    @Resource
    private ExtAxReModelService reModelService;

    /**
     * 获取流程模型的查询结果
     */
    @Operation(summary = "流程模型列表")
    @GetMapping("/page")
    @Override
    public CommonResponse<BpmPageResult<BpmnModelDetailVO>> page(@Validated @RequestBody BpmnModelSearchDTO dto) {
        log.info("获取流程模型getModelPage===>>>参数：{}", JSONUtil.toJsonStr(dto));
        BpmPageResult<BpmnModelDetailVO> result = bpmnProcessModelService.getModelPage(dto);
        return success(result);
    }

    /**
     * 创建流程模型
     * return modelId的主键
     */
    @Operation(summary = "创建流程模型")
    @PostMapping("/create")
    @Override
    @RepeatSubmit
    public CommonResponse<String> create(@Validated @RequestBody BpmnModelCreateDTO dto) {
        log.info("创建流程createBpmModel===>>>参数：{}", JSONUtil.toJsonStr(dto));
        String result = bpmnProcessModelService.createBpmModel(dto);
        return success(result);
    }

    /**
     * 通过 Xml 创建模型
     *
     * @return
     */
    @Operation(summary = "通过 Xml 创建模型", hidden = true)
    @PostMapping("/xml/create")
    public CommonResponse<String> createWithXml() {
        // TODO 不完善的接口
        return success(bpmnProcessModelService.createBpmModelWithXml(""));
    }

    /**
     * 通过模型 ID 获取模型
     */
    @Operation(summary = "通过模型ID查询指定流程模型")
    @GetMapping("/get")
    @Override
    public CommonResponse<BpmnModelDetailVO> getById(@NotBlank(message = "流程模型 ID 不能为空") @RequestParam String processModelId, @RequestParam(required = false) String tenantId) {
        log.info("获取模型getModelDetailById===>>>参数：{}", JSONUtil.toJsonStr(processModelId));
        BpmnModelDetailVO result = bpmnProcessModelService.getById(processModelId, tenantId);
        return success(result);
    }


    /**
     * 通过模型 KEY 获取模型
     */
    @Operation(summary = "通过模型KEY查询指定流程模型")
    @GetMapping("/getByKey")
    @Override
    public CommonResponse<BpmnModelDetailVO> getByKey(@NotBlank(message = "流程模型 KEY 不能为空") @RequestParam String processModelKey, @NotBlank(message = "租户不能为空") @RequestParam String tenantId) {
        log.info("获取模型getModelDetailByKey===>>>参数：{}", JSONUtil.toJsonStr(processModelKey));
        BpmnModelDetailVO result = bpmnProcessModelService.getByKey(processModelKey, tenantId);
        return success(result);
    }

    /**
     * 校验是否能更新模型即其关联的流程定义内容
     *
     * @param modelId 模型 ID
     * @return
     */
    @Operation(summary = "获取指定模型的扩展属性")
    @GetMapping("/ext")
    @Override
    public CommonResponse<BpmnModelExtVO> getModelExt(@NotBlank(message = "模型 ID 不能为空") @RequestParam(required =
            false) String modelId) {
        log.info("获取指定模型的扩展属性getModelExt===>>>参数：{}", JSONUtil.toJsonStr(modelId));
        return success(reModelService.getStatusByModelId(modelId));
    }

    /**
     * 修改流程信息
     */
    @Operation(summary = "更新流程模型")
    @PutMapping("/update")
    @Override
    public CommonResponse<String> update(@Validated @RequestBody BpmnModelUpdateDTO dto) {
        log.info("修改流程信息updateBpmModel===>>> 模型 ID: {}", dto.getProcessModelId());
        bpmnProcessModelService.updateBpmModel(dto);
        return success(dto.getProcessModelId());
    }


    /**
     * 通过模型 ID 部署模型
     *
     * @param modelTenantId  模型所属租户 ID
     * @param processModelId 模型 ID
     * @param operator       操作人信息
     * @return 部署完成的流程定义Id
     */
    @Operation(summary = "通过模型 ID 部署流程模型")
    @PostMapping("/deploy")
    @Override
    public CommonResponse<String> deployById(@NotBlank(message = "流程模型 ID 不能为空") @RequestParam(required = false) String processModelId, @RequestParam(required = false, defaultValue = "") String modelTenantId, @RequestParam(required = false) String operator) {
        log.info("部署模型deployBpmModelById===>>>参数：{}, 租户 ID: {}, operator: {}", JSONUtil.toJsonStr(processModelId),
                modelTenantId, operator);
        BpmnTaskDelegateAssigner assignee = JSON.parseObject(operator, BpmnTaskDelegateAssigner.class);
        String result = bpmnProcessModelService.deployBpmModelById(processModelId, modelTenantId, assignee);
        return success(result);
    }


    /**
     * 通过模型 KEY 部署模型
     *
     * @param processModelKey 模型 Key
     * @param modelTenantId   模型所属租户 ID
     * @param operator        操作人信息
     * @return 部署完成的流程定义Id
     */
    @Operation(summary = "通过模型 KEY 部署流程模型")
    @PostMapping("/deployByKey")
    @Override
    public CommonResponse<String> deployByKey(@NotBlank(message = "流程模型 KEY 不能为空") @RequestParam(required = false) String processModelKey, @NotBlank(message = "租户不能为空") @RequestParam(required = false) String modelTenantId, @RequestParam(required = false) String operator) {
        log.info("部署模型deployBpmModelByKey===>>>参数：{}", JSONUtil.toJsonStr(processModelKey));
        BpmnTaskDelegateAssigner assignee = JSON.parseObject(operator, BpmnTaskDelegateAssigner.class);
        String result = bpmnProcessModelService.deployBpmModelByKey(processModelKey, modelTenantId, assignee);
        return success(result);
    }

    /**
     * 通过模型 ID 取消部署流程模型
     *
     * @param processModelId 模型 ID
     * @param tenantId       租户 ID
     * @param operator       操作人信息
     * @return
     */
    @Operation(summary = "通过模块 ID 取消部署流程模型")
    @PostMapping("/undeploy")
    @Override
    public CommonResponse<Void> unDeployById(@NotBlank(message = "流程模型 ID 不能为空") @RequestParam(required = false) String processModelId,
                                             @RequestParam(required = false, defaultValue = "") String tenantId,
                                             @RequestParam(required = false) String operator) {
        log.info("部署模型unDeployBpmModelById===>>>参数：{}", JSONUtil.toJsonStr(processModelId));
        BpmnTaskDelegateAssigner assignee = JSON.parseObject(operator, BpmnTaskDelegateAssigner.class);
        bpmnProcessModelService.unDeployBpmModelById(processModelId, tenantId, assignee);
        return success();
    }

    /**
     * 通过模型 ID 删除模型
     *
     * @param processModelId 模型 ID
     * @param tenantId       租户 ID
     */
    @Operation(summary = "删除指定模型 ID 的流程模型")
    @DeleteMapping("/delete")
    @Override
    public CommonResponse<Void> deleteById(@NotBlank(message = "流程模型 ID 不能为空") @RequestParam String processModelId,
                                           @RequestParam(required = false, defaultValue = "") String tenantId) {
        log.info("删除模型deleteBpmModel===>>>参数：{}", JSONUtil.toJsonStr(processModelId));
        bpmnProcessModelService.deleteBpmModelById(processModelId, tenantId);
        return success();
    }

    /**
     * 通过模型 KEY 删除模型
     *
     * @param processModelKey 模型 KEY
     * @param tenantId        租户 ID
     * @return
     */
    @Operation(summary = "删除指定模型 KEY 的流程模型")
    @DeleteMapping("/deleteByKey")
    @Override
    public CommonResponse<Void> deleteByKey(@NotBlank(message = "流程模型 KEY 不能为空") @RequestParam String processModelKey,
                                            @RequestParam(required = false, defaultValue = "") String tenantId) {
        log.info("删除模型deleteBpmModel===>>>参数：{}", JSONUtil.toJsonStr(processModelKey));
        bpmnProcessModelService.deleteBpmModelByKey(processModelKey, tenantId);
        return success();
    }

    /**
     * 通过模型 ID 修改模型状态
     *
     * @param modelId  模型 ID
     * @param status   状态
     * @param operator 操作人
     * @return
     */
    @Operation(summary = "修改模型状态")
    @PostMapping("/changeStatus")
    @Override
    public CommonResponse<Void> changeStatus(@NotBlank(message = "模型 ID 不能为空") @RequestParam String modelId,
                                             @NotNull(message = "状态不能为空") @RequestParam Integer status,
                                             @RequestParam(required = false) String operator) {
        log.info("修改模型状态changeStatus===>>>参数：{}", JSONUtil.toJsonStr(modelId));
        BpmnTaskDelegateAssigner assignee = JSON.parseObject(operator, BpmnTaskDelegateAssigner.class);
        bpmnProcessModelService.changeStatus(modelId, status, assignee);
        return success();
    }

    /**
     * 查询流程模型使用的分类列表
     *
     * @return
     */
    @Operation(summary = "查询流程模型使用的分类列表")
    @GetMapping("/category/ids")
    @Override
    public CommonResponse<List<String>> getModelCategoryList() {
        log.info("获取已经使用过的分类集合getModelCategoryList");
        return success(bpmnProcessModelService.getModelCategoryList());
    }

    /**
     * 查询模型的租户集合
     *
     * @return
     */
    @Operation(summary = "查询模型的租户集合")
    @GetMapping("/tenant/ids")
    @Override
    public CommonResponse<List<String>> getTenantIds() {
        log.info("查询模型的租户集合getTenantIds");
        return success(bpmnProcessModelService.getTenantIds());
    }
}
