package cn.axzo.workflow.server.controller.listener.task;

import cn.axzo.nanopart.doc.api.anonymous.DocAnonymousDatabaseApi;
import cn.axzo.nanopart.doc.api.index.request.CopyNodeRequest;
import cn.axzo.workflow.common.enums.FileTypeEnum;
import cn.axzo.workflow.common.model.dto.SignFileDTO;
import cn.axzo.workflow.common.model.dto.VariableObjectDTO;
import cn.axzo.workflow.common.model.request.bpmn.BpmnSignConf;
import cn.axzo.workflow.common.model.request.bpmn.model.doc.DocCloneDTO;
import cn.axzo.workflow.common.model.response.bpmn.model.doc.DocBaseVO;
import cn.axzo.workflow.core.common.context.TaskOperationContext;
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
import cn.axzo.workflow.core.engine.cmd.CustomGetModelDocsCmd;
import cn.axzo.workflow.core.listener.AbstractBpmnEventListener;
import cn.axzo.workflow.core.listener.BpmnTaskEventListener;
import cn.axzo.workflow.core.repository.entity.ExtAxProcessSign;
import cn.axzo.workflow.core.repository.mapper.ExtAxModelDocMapper;
import cn.axzo.workflow.core.service.ExtAxModelDocService;
import cn.axzo.workflow.core.service.ExtAxProcessSignService;
import cn.axzo.workflow.core.service.ExtAxReModelService;
import cn.axzo.workflow.server.common.util.RpcExternalUtil;
import cn.axzo.workflow.server.common.util.WpsUtil;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.Process;
import org.flowable.common.engine.impl.interceptor.CommandExecutor;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
import org.flowable.task.service.delegate.DelegateTask;
import org.springframework.context.annotation.Scope;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_STARTER;

/**
 * 签署业务才会执行
 * <p>
 * 流程实例启用成功后:
 * 1、将模型关联的且实例勾选使用过的文档进行原始模板复制
 * 2、进行初始数据的模板变量替换
 * <p>
 * 并存至 ext_ax_process_sign 中的 doc_template 字段
 *
 * @author wangli
 * @since 2025-05-16 15:12
 */
@Slf4j
@Component
@Scope("prototype")
public class FirstCopyTemplateFileTaskEvent_105_Listener extends AbstractBpmnEventListener<TaskOperationContext> implements BpmnTaskEventListener, Ordered {
    @Resource
    private ExtAxProcessSignService extAxProcessSignService;
    @Resource
    private ExtAxModelDocMapper extAxModelDocMapper;
    @Resource
    private ExtAxReModelService extAxReModelService;
    @Resource
    private ExtAxModelDocService extAxModelDocService;
    @Resource
    private DocAnonymousDatabaseApi docAnonymousApi;
    @Resource
    private WpsUtil wpsUtil;

    @Override
    public void onCompleted(DelegateTask delegateTask) {
        if (!Objects.equals(NODE_STARTER.getType(), delegateTask.getTaskDefinitionKey())) {
            return;
        }
        String processInstanceId = delegateTask.getProcessInstanceId();

        Process mainProcess = ProcessDefinitionUtil.getBpmnModel(delegateTask.getProcessDefinitionId()).getMainProcess();
        Optional<BpmnSignConf> signConfig = BpmnMetaParserHelper.getSignConfig(mainProcess);
        if (!signConfig.isPresent() || Objects.isNull(signConfig.get().getSignType())) {
            return;
        }

        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
        CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor();
        List<DocBaseVO> docs = commandExecutor.execute(new CustomGetModelDocsCmd(processInstanceId, true, extAxModelDocMapper, extAxReModelService));
        ExtAxProcessSign processSign = new ExtAxProcessSign();
        processSign.setProcessInstanceId(processInstanceId);
        processSign.setSignType(signConfig.get().getSignType().getType());
        processSign.setPendingMessageId(signConfig.get().getSignPendingProperty().getPendingMessageId());
        if (CollectionUtils.isEmpty(docs)) {
            processSign.setDocTemplate(Collections.emptyList());
            processSign.setFileArchive(Collections.emptyList());
        } else {
            // 复制基础模板
            List<SignFileDTO> docTemplates = copyTempTemplate(docs);
            processSign.setDocTemplate(docTemplates);

            List<SignFileDTO> archives = replaceTemplateVariable(docTemplates, processEngineConfiguration, processInstanceId);
            processSign.setFileArchive(archives);
        }
        // 没有可用的文档，但仍然记录库表
        extAxProcessSignService.save(processSign);
    }

    private List<SignFileDTO> replaceTemplateVariable(List<SignFileDTO> docTemplates, ProcessEngineConfigurationImpl processEngineConfiguration, String processInstanceId) {
        List<SignFileDTO> archives = new ArrayList<>();
        List<VariableObjectDTO> wpsReplaceVariables = wpsUtil.getWpsReplaceVariables(processEngineConfiguration, processInstanceId);
        docTemplates.forEach(template -> {
            SignFileDTO signFileDTO = new SignFileDTO();
            signFileDTO.setId(template.getId());
            signFileDTO.setFileName(template.getFileName());
            signFileDTO.setTemplateName(template.getTemplateName());
            signFileDTO.setFileTag(template.getFileTag());
            signFileDTO.setFileType(template.getFileType());
            signFileDTO.setFileCode(template.getFileCode());
            if (Objects.equals(template.getFileType(), FileTypeEnum.WORD) || Objects.equals(template.getFileType(), FileTypeEnum.EXCEL)) {
                String fileKey = wpsUtil.wpsFileVariableReplace(wpsReplaceVariables, template.getFileCode(), null, template.getTemplateName() + template.getFileType().getSuffix());
                signFileDTO.setFileKey(fileKey);
            }
            archives.add(signFileDTO);
        });
        return archives;
    }

    private List<SignFileDTO> copyTempTemplate(List<DocBaseVO> docs) {
        List<SignFileDTO> files = new ArrayList<>();
        docs.forEach(doc -> {
            SignFileDTO signFileDTO = new SignFileDTO();
            // 原始文档 ID
            signFileDTO.setId(doc.getId());
            signFileDTO.setFileName(doc.getFileName());
            signFileDTO.setTemplateName(doc.getTemplateName());
            signFileDTO.setFileTag(doc.getTag());
            signFileDTO.setFileType(doc.getFileType());
            switch (doc.getFileType()) {
                case WORD:
                case EXCEL:
                    CopyNodeRequest copy = new CopyNodeRequest();
                    copy.setCode(doc.getFileRelationId());
                    String fileCode = RpcExternalUtil.rpcProcessor(() -> docAnonymousApi.copy(copy), "复制文档", copy);
                    signFileDTO.setFileCode(fileCode);
                    break;
                case HIPRINT:
                    Long newDocId = extAxModelDocService.cloneDoc(DocCloneDTO.builder().docId(doc.getId()).build(), true);
                    signFileDTO.setFileCode(String.valueOf(newDocId));
                    break;
                case PDF:
                    break;
                default:
                    break;
            }
            files.add(signFileDTO);
        });
        return files;
    }

    @Override
    public int getOrder() {
        return Integer.MIN_VALUE + 105;
    }
}
