package com.fjhx.service.process.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.constants.FlowConstant;
import com.fjhx.constants.FlowExplainConstant;
import com.fjhx.constants.StatusConstant;
import com.fjhx.entity.process.ProcessNode;
import com.fjhx.entity.process.ProcessTenant;
import com.fjhx.enums.ProcessNodeHandleObjectTypeEnum;
import com.fjhx.enums.ProcessNodeTypeEnum;
import com.fjhx.mapper.process.ProcessTenantMapper;
import com.fjhx.params.NodeDetailsVo;
import com.fjhx.service.process.ProcessNodeButtonService;
import com.fjhx.service.process.ProcessTenantService;
import com.fjhx.utils.Assert;
import com.fjhx.utils.WrapperUtil;
import org.springblade.common.constant.CommonConstant;
import org.springblade.core.secure.utils.AuthUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 租户流程表 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2022-08-16
 */
@Service
public class ProcessTenantServiceImpl extends ServiceImpl<ProcessTenantMapper, ProcessTenant> implements ProcessTenantService {

    @Lazy
    @Autowired
    private ProcessNodeButtonService processNodeButtonService;

    @Override
    public Page<Map<String, Object>> getPage(Map<String, String> condition) {

        QueryWrapper<?> wrapper = WrapperUtil.init(condition)
                .eq("pt.binding_tenant_id", "bindingTenantId", "租户id不能为空")
                .eq("pi.service_name", "serviceName")
                .keyword("pi.module_name", "pt.name")
                .getWrapper()
                .eq("pt.current_version", StatusConstant.YES);

        return baseMapper.getPage(createPage(condition), wrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(ProcessTenant processTenant) {

        // 流程id
        Long processInfoId = processTenant.getProcessInfoId();
        Assert.notEmpty(processInfoId, FlowExplainConstant.PROCESS_INFO_ID_EMPTY);

        // 流程名称
        String name = processTenant.getName();
        Assert.notEmpty(name, FlowExplainConstant.PROCESS_NAME);

        // 租户id
        String bindingTenantId = processTenant.getBindingTenantId();
        if (ObjectUtil.isEmpty(bindingTenantId)) {
            processTenant.setBindingTenantId(AuthUtil.getTenantId());
        }

        // 判断流程是否存在
        Long count = count(Wrappers.<ProcessTenant>lambdaQuery()
                .eq(ProcessTenant::getBindingTenantId, processTenant.getBindingTenantId())
                .eq(ProcessTenant::getProcessInfoId, processInfoId));
        Assert.eqZero(count, FlowExplainConstant.PROCESS_EXIST);

        // 赋值默认版本号
        processTenant.setVersionNumber(FlowConstant.DEFAULT_VERSION_NUMBER);
        processTenant.setCurrentVersion(StatusConstant.YES);

        // 保存数据
        save(processTenant);

        // 生成默认节点
        createProcess(processTenant.getId());

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addVersion(NodeDetailsVo nodeDetailsVo) {

        // 查询流程最大版本信息
        ProcessTenant newProcessTenant = getOne(Wrappers.<ProcessTenant>lambdaQuery()
                .eq(ProcessTenant::getProcessInfoId, nodeDetailsVo.getProcessInfoId())
                .eq(ProcessTenant::getBindingTenantId, nodeDetailsVo.getBindingTenantId())
                .orderByDesc(ProcessTenant::getVersionNumber)
                .last("limit 1")
        );

        // id设为空
        newProcessTenant.setId(null);

        // 版本号+1 设为非当前流程
        newProcessTenant.setVersionNumber(newProcessTenant.getVersionNumber() + 1);
        newProcessTenant.setCurrentVersion(StatusConstant.NO);

        newProcessTenant.setLineObject(nodeDetailsVo.getLineObject());
        newProcessTenant.setNodeObject(nodeDetailsVo.getNodeObject());

        // 保存数据
        save(newProcessTenant);

        nodeDetailsVo.setProcessTenantId(newProcessTenant.getId());

        // 生成节点
        processNodeButtonService.insertNodeButton(nodeDetailsVo);

    }

    @Override
    public List<ProcessTenant> getVersionByProcessInfoId(ProcessTenant processTenant) {
        return list(Wrappers.<ProcessTenant>lambdaQuery()
                .eq(ProcessTenant::getBindingTenantId, processTenant.getBindingTenantId())
                .eq(ProcessTenant::getProcessInfoId, processTenant.getProcessInfoId()));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void editVersion(ProcessTenant processTenant) {

        Long processInfoId = processTenant.getProcessInfoId();
        String bindingTenantId = processTenant.getBindingTenantId();

        update(Wrappers.<ProcessTenant>lambdaUpdate()
                .set(ProcessTenant::getCurrentVersion, StatusConstant.NO)
                .eq(ProcessTenant::getProcessInfoId, processInfoId)
                .eq(ProcessTenant::getBindingTenantId, bindingTenantId));

        processTenant.setCurrentVersion(StatusConstant.YES);
        updateById(processTenant);
    }

    @Override
    public ProcessTenant getProcessTenant(String code, String tenantId) {
        return baseMapper.getProcessTenant(code, tenantId);
    }

    /**
     * 生成默认流程
     */
    private void createProcess(Long processTenantId) {

        // 生成默认开始节点
        ProcessNode startProcessNode = new ProcessNode();
        startProcessNode.setId(FlowConstant.TEMP_START_NODE_ID);
        startProcessNode.setType(ProcessNodeTypeEnum.START.getType());
        startProcessNode.setParentId(CommonConstant.TOP_PARENT_ID);
        startProcessNode.setName(FlowConstant.START_NAME);
        startProcessNode.setCode(FlowConstant.START_CODE);
        startProcessNode.setHandleObjectType(ProcessNodeHandleObjectTypeEnum.ALL.getType());

        // 生成默认结束节点
        ProcessNode endProcessNode = new ProcessNode();
        endProcessNode.setId(FlowConstant.TEMP_END_NODE_ID);
        endProcessNode.setType(ProcessNodeTypeEnum.END.getType());
        endProcessNode.setParentId(FlowConstant.TEMP_START_NODE_ID);
        endProcessNode.setName(FlowConstant.END_NAME);
        endProcessNode.setCode(FlowConstant.END_CODE);

        List<ProcessNode> processNodeList = Arrays.asList(startProcessNode, endProcessNode);

        NodeDetailsVo nodeDetailsVo = new NodeDetailsVo();
        nodeDetailsVo.setProcessTenantId(processTenantId);
        nodeDetailsVo.setProcessNodeList(processNodeList);

        processNodeButtonService.insertNodeButton(nodeDetailsVo);
    }

}
