package com.prolog.rdc.tms.app.service.flow;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.rdc.tms.app.constant.SeriaNnumberConstant;
import com.prolog.rdc.tms.app.dao.mapper.TmsLoadingBillDetailMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsLoadingBillHeaderMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillDetailMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillHeaderMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillNodeTrackingMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillOperateLogMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillTransportLogMapper;
import com.prolog.rdc.tms.app.model.entity.ShipbillNodeTracking;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillOperateLogModel;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillTransLogModel;
import com.prolog.rdc.tms.app.proxy.MainDataProxy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * @author hongbo.pan
 * @date 2022/10/17
 */
@Slf4j
public abstract class FlowNodeHandle {

    @Autowired
    protected MainDataProxy mainDataProxy;

    @Autowired
    protected TmsShipbillHeaderMapper tmsShipbillHeaderMapper;

    @Autowired
    protected TmsShipbillDetailMapper tmsShipbillDetailMapper;

    @Autowired
    protected TmsLoadingBillDetailMapper tmsLoadingBillDetailMapper;

    @Autowired
    protected TmsLoadingBillHeaderMapper tmsLoadingBillHeaderMapper;

    @Autowired
    private TmsShipbillNodeTrackingMapper tmsShipbillNodeTrackingMapper;

    @Autowired
    private TmsShipbillOperateLogMapper tmsShipbillOperateLogMapper;

    @Autowired
    private TmsShipbillTransportLogMapper tmsShipbillTransportLogMapper;

    /**
     * 节点处理
     * @param context
     */
    protected abstract void doHandle(FlowContext context);

    /**
     * 流程节点
     * @return
     */
    protected abstract String getFlowNode();

    /**
     * buildShipBillNodeTracking
     * @return
     */
    protected abstract ShipbillNodeTracking buildShipBillNodeTracking();

    /**
     * buildShipBillNodeTracking
     * @return
     */
    protected abstract TmsShipbillOperateLogModel buildShipBillOperateLog();

    /**
     * buildShipBillTransLog
     * @return
     */
    protected abstract TmsShipbillTransLogModel buildShipBillTransLog();

    @Transactional(rollbackFor = Exception.class)
    public void nodeHandle(FlowContext context) {
        if (StrUtil.isNotBlank(context.getFlowConfig()) && context.getFlowConfig().contains(getFlowNode())) {
            log.info("nodeHandle={},context={}", this.getClass().getSimpleName(), JSON.toJSONString(context));
            doHandle(context);
            // 运单节点保存
            addNodeTrackingData(context);
            // 运单操作日志保存
            addOperateLogData(context);
            // 订单运输记录表
            addOrUpdateTransportLog(context);
        }
    }

    private void addNodeTrackingData(FlowContext context) {
        ShipbillNodeTracking shipbillNodeTracking = buildShipBillNodeTracking();
        String id = mainDataProxy.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_NODE_TRACKING_ID);
        shipbillNodeTracking.setId(id);
        shipbillNodeTracking.setShipbillId(context.getTmsShipBillHeaderModel().getShipbillId());
        shipbillNodeTracking.setShipbillNo(context.getTmsShipBillHeaderModel().getShipbillNo());
        shipbillNodeTracking.setNodeDate(new Date());
        shipbillNodeTracking.setUserId(context.getUserEntity().getUserid());
        shipbillNodeTracking.setUserName(context.getUserEntity().getNickname());
        shipbillNodeTracking.setEnterpriseId(context.getUserEntity().getEnterpriseId());
        shipbillNodeTracking.setEnterpriseName(context.getUserEntity().getEnterpriseName());
        shipbillNodeTracking.setCreateperson(context.getUserEntity().getNickname());
        shipbillNodeTracking.setCreatetime(new Date());
        shipbillNodeTracking.setUpdateperson(context.getUserEntity().getNickname());
        shipbillNodeTracking.setUpdatetime(new Date());
        tmsShipbillNodeTrackingMapper.save(shipbillNodeTracking);
    }

    private void addOperateLogData(FlowContext context) {
        TmsShipbillOperateLogModel tmsShipbillOperateLogModel = buildShipBillOperateLog();
        String id = mainDataProxy.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_OPERATE_LOG_ID);
        tmsShipbillOperateLogModel.setId(id);
        tmsShipbillOperateLogModel.setShipbillId(context.getTmsShipBillHeaderModel().getShipbillId());
        tmsShipbillOperateLogModel.setShipbillNo(context.getTmsShipBillHeaderModel().getShipbillNo());
        tmsShipbillOperateLogModel.setOperateDate(new Date());
        tmsShipbillOperateLogModel.setUserId(context.getUserEntity().getUserid());
        tmsShipbillOperateLogModel.setUserName(context.getUserEntity().getNickname());
        tmsShipbillOperateLogModel.setEnterpriseId(context.getUserEntity().getEnterpriseId());
        tmsShipbillOperateLogModel.setEnterpriseName(context.getUserEntity().getEnterpriseName());
        tmsShipbillOperateLogModel.setCreateperson(context.getUserEntity().getNickname());
        tmsShipbillOperateLogModel.setCreatetime(new Date());
        tmsShipbillOperateLogModel.setUpdateperson(context.getUserEntity().getNickname());
        tmsShipbillOperateLogModel.setUpdatetime(new Date());
        tmsShipbillOperateLogMapper.save(tmsShipbillOperateLogModel);
    }

    private void addOrUpdateTransportLog(FlowContext context) {
        Criteria criteria = Criteria.forClass(TmsShipbillTransLogModel.class);
        Restriction r1 = Restrictions.eq(TmsShipbillTransLogModel::getShipbillId, context.getTmsShipBillHeaderModel().getShipbillId());
        Restriction r2 = Restrictions.eq(TmsShipbillTransLogModel::getEnterpriseId, context.getUserEntity().getEnterpriseId());
        criteria.setRestriction(Restrictions.and(r1, r2));
        List<TmsShipbillTransLogModel> logModelList = tmsShipbillTransportLogMapper.findByCriteria(criteria);
        TmsShipbillTransLogModel tmsShipbillTransLogModel = buildShipBillTransLog();
        tmsShipbillTransLogModel.setUpdateperson(context.getUserEntity().getNickname());
        tmsShipbillTransLogModel.setUpdatetime(new Date());
        if (CollectionUtil.isEmpty(logModelList)) {
            String id = mainDataProxy.getCodeNumberByCode(SeriaNnumberConstant.TMS_SHIPBILL_TRANSPORT_LOG_ID);
            tmsShipbillTransLogModel.setId(id);
            tmsShipbillTransLogModel.setShipbillId(context.getTmsShipBillHeaderModel().getShipbillId());
            tmsShipbillTransLogModel.setShipbillNo(context.getTmsShipBillHeaderModel().getShipbillNo());
            tmsShipbillTransLogModel.setEstimatedPickupStartTime(context.getTmsShipBillHeaderModel().getEstimatedPickupStartTime());
            tmsShipbillTransLogModel.setEnterpriseId(context.getUserEntity().getEnterpriseId());
            tmsShipbillTransLogModel.setEnterpriseName(context.getUserEntity().getEnterpriseName());
            tmsShipbillTransLogModel.setCreateperson(context.getUserEntity().getNickname());
            tmsShipbillTransLogModel.setCreatetime(new Date());
            tmsShipbillTransportLogMapper.save(tmsShipbillTransLogModel);
        } else {
            if (CollectionUtil.isNotEmpty(context.getTmsLoadingBillDetailModelList())) {
                tmsShipbillTransLogModel.setLoadingBillDetailId(context.getTmsLoadingBillDetailModelList().get(0).getId());
            }
            TmsShipbillTransLogModel dbLogModel = logModelList.get(0);
            BeanUtil.copyProperties(tmsShipbillTransLogModel, dbLogModel, CopyOptions.create().ignoreNullValue());
            tmsShipbillTransportLogMapper.update(dbLogModel);
        }
    }
}
