package cn.axzo.workflow.core.service.impl;

import cn.axzo.workflow.common.model.dto.BpmnFormRelationCreateDTO;
import cn.axzo.workflow.common.model.request.bpmn.model.BpmnModelCreateDTO;
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.request.form.model.FormModelUpdateDTO;
import cn.axzo.workflow.core.service.AggregateModelService;
import cn.axzo.workflow.core.service.BpmnProcessModelService;
import cn.axzo.workflow.core.service.ExtAxBpmnFormRelationService;
import cn.axzo.workflow.form.service.FormModelService;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ProcessDefinition;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Nullable;
import javax.annotation.Resource;
import java.util.Objects;

import static cn.axzo.workflow.common.constant.BpmnConstants.FORM_FILE_SUFFIX;
import static cn.axzo.workflow.common.constant.BpmnConstants.NO_TENANT_ID;

/**
 * 聚合审批模型和表单模型的操作服务
 *
 * @author wangli
 * @since 2024-11-05 16:38
 */
@Slf4j
@Service
public class AggregateModelServiceImpl implements AggregateModelService {

    @Resource
    private BpmnProcessModelService bpmnProcessModelService;
    @Resource
    private FormModelService formModelService;
    @Resource
    private RepositoryService repositoryService;
    @Resource
    private ExtAxBpmnFormRelationService formRelationService;

    @Transactional(rollbackFor = Exception.class)
    public String createBpmnAndFormModel(BpmnModelCreateDTO dto) {
        String bpmModelId = bpmnProcessModelService.createBpmModel(dto);

        if (Objects.nonNull(dto.getFormJsonModel()) && !CollectionUtils.isEmpty(dto.getFormJsonModel().getFormFields())) {
            Model formModel = repositoryService.createModelQuery().modelKey(dto.getKey())
                    .modelTenantId(dto.getTenantId())
                    .modelCategory(FORM_FILE_SUFFIX).singleResult();
            FormModelUpdateDTO formModelDto = new FormModelUpdateDTO();
            formModelDto.setKey(dto.getKey());
            formModelDto.setName(dto.getName());
            formModelDto.setFormFields(dto.getFormJsonModel().getFormFields());
            formModelDto.setTenantId(StringUtils.hasText(dto.getTenantId()) ? dto.getTenantId() : NO_TENANT_ID);
            if (Objects.isNull(formModel)) {
                formModelService.createFormModel(formModelDto);
            } else {
                formModelDto.setFormModelId(formModel.getId());
                formModelService.updateFormModel(formModelDto);
            }
        }
        return bpmModelId;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String updateBpmnAndFormModel(BpmnModelUpdateDTO dto) {
        bpmnProcessModelService.updateBpmModel(dto);

        // 如果没有表单字段就操作表单模型
        if (Objects.nonNull(dto.getFormJsonModel())) {
            FormModelUpdateDTO formModel = new FormModelUpdateDTO();
            formModel.setKey(dto.getKey());
            formModel.setName(dto.getName());
            formModel.setTenantId(dto.getTenantId());
            formModel.setFormFields(dto.getFormJsonModel().getFormFields());
            formModelService.updateFormModel(formModel);
        }
        return dto.getProcessModelId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String deployBpmnAndFormModel(String processModelId, @Nullable String tenantId, BpmnTaskDelegateAssigner operator) {
        String definitionId = bpmnProcessModelService.deployBpmModelById(processModelId, tenantId, operator);

        Model model = this.repositoryService.getModel(processModelId);
        Model formModel = repositoryService.createModelQuery()
                .modelKey(model.getKey())
                .modelCategory(FORM_FILE_SUFFIX)
                .modelTenantId(StringUtils.hasText(tenantId) ? tenantId : NO_TENANT_ID)
                .singleResult();
        if (Objects.isNull(formModel)) {
            return definitionId;
        }
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(definitionId).singleResult();
        String formDeploymentId = formModelService.deployFormModelById(formModel.getId(), tenantId, processDefinition.getDeploymentId());

        if (StringUtils.hasText(formDeploymentId)) {
            // 保存关联关系
            BpmnFormRelationCreateDTO relation = new BpmnFormRelationCreateDTO();
            relation.setKey(model.getKey());
            relation.setBpmnDefinitionId(definitionId);
            relation.setFormDeploymentId(formDeploymentId);
            relation.setTenantId(tenantId);
            formRelationService.insert(relation);
        }

        return definitionId;
    }
}
