package com.patzn.lims.consume.service.impl;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.google.common.collect.Lists;
import com.patzn.lims.common.DateUtils;
import com.patzn.lims.consume.entity.LmsChemicalDeliveryOrder;
import com.patzn.lims.consume.enums.DeliveryOrderEnum;
import com.patzn.lims.consume.mapper.LmsChemicalDeliveryOrderMapper;
import com.patzn.lims.consume.service.ILmsChemicalDeliveryOrderService;
import com.patzn.lims.consume.service.ILmsChemicalRelDeliveryService;
import com.patzn.lims.consume.vo.LmsChemicalDeliveryOrderVO;
import com.patzn.lims.core.api.PtAssert;
import com.patzn.lims.core.web.Account;
import com.patzn.lims.core.web.BaseServiceImpl;
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.patzn.lims.core.web.LoginHelper;
import com.patzn.lims.res.enums.CodeTypeEnum;
import com.patzn.lims.res.service.ILmsCodeRuleService;
import com.patzn.lims.workflow.FlowInfo;
import com.patzn.lims.workflow.FlowProcess;
import com.patzn.lims.workflow.FlowType;
import com.patzn.lims.workflow.FlowVariables;
import com.patzn.lims.workflow.service.IFlowProcessService;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * <p>
 * 试验耗材出库单表 服务实现类
 * </p>
 *
 * @author wwd
 * @since 2020-03-25
 */
@Service
public class LmsChemicalDeliveryOrderServiceImpl extends BaseServiceImpl<LmsChemicalDeliveryOrderMapper, LmsChemicalDeliveryOrder> implements ILmsChemicalDeliveryOrderService {

    @Autowired
    private ILmsCodeRuleService lmsCodeRuleService;
    @Autowired
    private ILmsChemicalRelDeliveryService lmsChemicalRelDeliveryService;
    @Autowired
    private IFlowProcessService flowProcessService;

    @Override
    public Page<LmsChemicalDeliveryOrder> page(Page<LmsChemicalDeliveryOrder> page, LmsChemicalDeliveryOrderVO chemicalDeliveryOrder) {
        QueryWrapper<LmsChemicalDeliveryOrder> ew = Wrappers.<LmsChemicalDeliveryOrder>query(chemicalDeliveryOrder);

        if (null != chemicalDeliveryOrder.getNum()) {
            ew.like("num", chemicalDeliveryOrder.getNum());
            chemicalDeliveryOrder.setNum(null);
        }
        if (null != chemicalDeliveryOrder.getRemark()) {
            ew.like("remark", chemicalDeliveryOrder.getRemark());
            chemicalDeliveryOrder.setRemark(null);
        }
        return this.page(page, ew);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean save(boolean approve, LmsChemicalDeliveryOrder lmsChemicalDeliveryOrder,Long userId) {
        LmsChemicalDeliveryOrder lcdo = new LmsChemicalDeliveryOrder();
        lcdo.setId(IdWorker.getId());
        //生成编号
        if (null != lmsCodeRuleService.getCodeRule(CodeTypeEnum.CHEMICAL_APPLY)) {
            lcdo.setNum(lmsCodeRuleService.getKey(CodeTypeEnum.CHEMICAL_APPLY, lcdo));
        } else {
            lcdo.setNum("DN" + lcdo.getId());
        }

        lcdo.setRemark(lmsChemicalDeliveryOrder.getRemark());
        // 修改临时采购池中的采购单 ID 状态
        Account account = LoginHelper.getAccount();
        lmsChemicalRelDeliveryService.updateOrderStatus(lcdo.getId(), account.getUserId());
        if (approve) {
            // 提交审批
            lcdo.setStatus((Integer) DeliveryOrderEnum.IN_APPROVAL.getValue());
            List<FlowInfo> flowInfoList = new ArrayList<>();
            flowInfoList.add(FlowInfo.convertFlowInfo(FlowType.CHEMICAL_DELIVERY,
                    account, lcdo.getId(), lcdo.getRemark()));
            flowProcessService.saveTask(flowInfoList,account);
            if(null != userId){
//                lmsMsgService.sendMsg("/lims/chemical_out_storage_apply","请前往-系统管理-工作流管理-我的任务中查看详情,请确保您处于工作组中。",
//                        "新的耗材使用申请需要您的审批",account, Lists.newArrayList( ));
            }
        } else {
            // 待提交
            lcdo.setStatus((Integer) DeliveryOrderEnum.WAIT_APPROVAL.getValue());
        }
        lcdo.setApplyer(account.getUserName());
        lcdo.setDepId(lmsChemicalDeliveryOrder.getDepId());
        lcdo.setDepartment(lmsChemicalDeliveryOrder.getDepartment());
        lcdo.setRegistrant(lmsChemicalDeliveryOrder.getRegistrant());
        return save(lcdo);
    }



    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<FlowProcess> submitDeliveryFlow(Long[] ids, Long sendUserId) {
        if (null == ids || ids.length <= 0) {
            return null;
        }
        List<LmsChemicalDeliveryOrder> lcpoList = new ArrayList<>();
        List<FlowInfo> flowInfoList = new ArrayList<>();
        for (Long id : ids) {
            LmsChemicalDeliveryOrder lcpo = getById(id);
            if (null != lcpo) {
                Account account = LoginHelper.getAccount();
                FlowInfo flowInfo = new FlowInfo();
                flowInfo.setFlowType(FlowType.CHEMICAL_DELIVERY.getValue());
                flowInfo.setId(lcpo.getId());
                flowInfo.setApplyId(account.getUserIdStr());
                flowInfo.setApplyName(account.getUserName());
                flowInfo.setRemark(lcpo.getRemark());
                flowInfo.setApplyTime(new Date());
                // 设置出库单审批中
                lcpo = new LmsChemicalDeliveryOrder();
                lcpo.setId(id);
                lcpo.setApplyer(account.getUserName());
                lcpo.setStatus((Integer) DeliveryOrderEnum.IN_APPROVAL.getValue());
                lcpoList.add(lcpo);
                flowInfoList.add(flowInfo);
            }
        }
        updateBatchById(lcpoList);
        if(null != sendUserId ){
//            lmsMsgService.sendMsg("/lims/chemical_out_storage_apply","请前往-系统管理-工作流管理-我的任务中查看详情,请确保您处于工作组中。",
//                    "新的耗材使用申请需要您的审批",LoginHelper.getAccount(), Lists.newArrayList(sendUserId));
        }
        return flowProcessService.saveTask(flowInfoList,LoginHelper.getAccount());
    }



    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean approveDeliveryFlow(String taskId, String allow, String postil, String step) {
        FlowInfo flowInfo = null;
        DeliveryOrderEnum deliveryOrderEnum = null;
        Account account = LoginHelper.getAccount();
        if ("finish".equals(step)) {
            // 确认审批通过
            flowInfo = flowProcessService.complete(taskId);
            deliveryOrderEnum = DeliveryOrderEnum.WAIT_DELIVERY;
        } else if ("rejectFinish".equals(step)) {
            flowInfo = flowProcessService.complete(taskId);
            deliveryOrderEnum = DeliveryOrderEnum.FINISH;
        } else {
            // 正常审批
            FlowVariables flowVariables = new FlowVariables(taskId);
            Map<String, Object> map = new HashMap<>(4);
            if ("5".equals(allow)) {
                // 驳回
                map.put(FlowInfo.APPLY_ID, account.getUserId());
                deliveryOrderEnum = DeliveryOrderEnum.APPROVAL_REJECT;
            } else if ("3".equals(allow)) {
                //通过
                deliveryOrderEnum = DeliveryOrderEnum.WAIT_DELIVERY;
            } else if ("2".equals(allow)) {
                //终止
                map.put(FlowInfo.APPLY_ID, account.getUserId());
                deliveryOrderEnum = DeliveryOrderEnum.APPROVAL_FAILED;
            }
            map.put("technicalDirectorAduitPass", "3".equals(allow) ? true : false);
            if (StringUtils.isNotEmpty(postil)) {
                map.put("remark", postil);
            }
            flowVariables.setVariables(map);
            flowInfo = flowProcessService.complete(flowVariables);
        }
        if (null == flowInfo) {
            PtAssert.fail("确认审批失败！");
        }
        PtAssert.fail(null == flowInfo, "确认审批失败！");
        // 设置批注内容
        PtAssert.fail(!postil(account, flowInfo.getId(), postil, deliveryOrderEnum), "出库单状态设置失败请重试！");
        return null != flowInfo;
    }



    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean approvePurchaseFlowNews(String taskId, String postil, String allow, Long orderId, Long userId) {
        LmsChemicalDeliveryOrder lcdo = super.getById(orderId);
        if (null == lcdo) {
            return false;
        }

        FlowInfo flowInfo = null;
        Account account = LoginHelper.getAccount();
        {
            // 正常审批
            FlowVariables flowVariables = new FlowVariables(taskId);
            Map<String, Object> map = new HashMap<>(4);

            if ("back".equals(allow)) {
                // 驳回
                map.put(FlowInfo.APPLY_ID, account.getUserId());
                if (inApproval(lcdo.getStatus())) {
                    map.put("oneCheckBack", true);
                    map.put("oneToTwoCheck", false);
                    map.put("oneCheckPass", false);
                } else {
                    map.put("twoCheckBack", true);
                    map.put("twoCheckPass", false);
                }
                lcdo.setStatus((Integer) DeliveryOrderEnum.APPROVAL_REJECT.getValue());
            } else if ("pass".equals(allow)) {
                //通过
                if (inApproval(lcdo.getStatus())) {
                    map.put("oneCheckPass", true);
                    map.put("oneCheckBack", false);
                    map.put("oneToTwoCheck", false);
                } else {
                    map.put("twoCheckBack", false);
                    map.put("twoCheckPass", true);
                }
                lcdo.setStatus((Integer) DeliveryOrderEnum.WAIT_DELIVERY.getValue());

            } else if ("down".equals(allow)) {
                //下级
                map.put(FlowInfo.APPLY_ID, account.getUserId());
                lcdo.setStatus((Integer)DeliveryOrderEnum.SECONDARY_APPROVAL.getValue());
                map.put("oneToTwoCheck", true);
                map.put("oneCheckPass", false);
                map.put("oneCheckBack", false);
            }else if("stop".equals(allow)){
                map.put(FlowInfo.APPLY_ID, account.getUserId());
                if (inApproval(lcdo.getStatus())) {
                    map.put("oneCheckBack", true);
                    map.put("oneToTwoCheck", false);
                    map.put("oneCheckPass", false);
                } else {
                    map.put("twoCheckBack", true);
                    map.put("twoCheckPass", false);
                }
                lcdo.setStatus((Integer) DeliveryOrderEnum.APPROVAL_FAILED.getValue());
            }

            if (StringUtils.isNotEmpty(postil)) {
                map.put("remark", postil);
            }
            flowVariables.setVariables(map);
            flowInfo = flowProcessService.complete(flowVariables);
        }
        if (null == flowInfo) {
            PtAssert.fail("确认审批失败！");
        }
        PtAssert.fail(null == flowInfo, "确认审批失败！");
        // 设置批注内容
        PtAssert.fail(!newspostil(account, lcdo, postil), "出库单状态设置失败请重试！");
        if (null != userId && Objects.equals("down", allow)) {
//            lmsMsgService.sendMsg("/lims/chemical_out_storage_apply", "请前往-系统管理-工作流管理-我的任务中查看详情,请确保您处于工作组中。",
//                    "新的耗材出库单出库需要您的审批", account, Lists.newArrayList(userId));
        }
        return null != flowInfo;
    }



    public boolean postil(Account account, Long id, String postil, DeliveryOrderEnum deliveryOrderEnum) {
        LmsChemicalDeliveryOrder lcdo = getById(id);
        LmsChemicalDeliveryOrder tempLcdo = new LmsChemicalDeliveryOrder();
        tempLcdo.setId(lcdo.getId());
        // 追加批注内容
        StringBuffer tempPostil = new StringBuffer();
        if (null != lcdo.getPostil()) {
            tempPostil.append(lcdo.getPostil()).append(" | ");
        }
        tempPostil.append(postil).append("【");
        tempPostil.append(account.getUserName()).append(", ");
        tempPostil.append(DateTime.now().toString("yyyy-MM-dd HH:mm:ss"));
        tempPostil.append("】");
        tempLcdo.setPostil(tempPostil.toString());
        if (null != deliveryOrderEnum) {
            // 完成审核进入待出库状态
            tempLcdo.setStatus((Integer) deliveryOrderEnum.getValue());
        }
        tempLcdo.setAuditor(account.getUserName());
        tempLcdo.setAuditorId(account.getUserId());
        tempLcdo.setAuditorDate(new Date());
        return super.updateById(tempLcdo);
    }

    public boolean inApproval(DeliveryOrderEnum status) {
        return status == DeliveryOrderEnum.IN_APPROVAL;
    }

    public boolean inApproval(Integer status) {
        return status == (Integer) DeliveryOrderEnum.IN_APPROVAL.getValue();
    }

    public boolean newspostil(Account account, LmsChemicalDeliveryOrder lcdo, String postil) {
        LmsChemicalDeliveryOrder tempLcdo = new LmsChemicalDeliveryOrder();
        tempLcdo.setId(lcdo.getId());
        // 追加批注内容
        StringBuffer tempPostil = new StringBuffer();
        if (null != lcdo.getPostil()) {
            tempPostil.append(lcdo.getPostil()).append(" | ");
        }
        if(StringUtils.isNotEmpty(postil)){
            tempPostil.append(postil);
        }else {
            tempPostil.append("【");
        }
        tempPostil.append(account.getUserName()).append(", ");
        tempPostil.append(DateTime.now().toString("yyyy-MM-dd HH:mm:ss"));
        tempPostil.append("】");
        tempLcdo.setPostil(tempPostil.toString());
        tempLcdo.setAuditor(account.getUserName());
        tempLcdo.setAuditorId(account.getUserId());
        tempLcdo.setStatus(lcdo.getStatus());
        tempLcdo.setAuditorDate(new Date());
        return super.updateById(tempLcdo);
    }



    @Override
    public Page<LmsChemicalDeliveryOrder> pageWaitDelivery(Page<LmsChemicalDeliveryOrder> page, LmsChemicalDeliveryOrderVO chemicalDeliveryOrder) {
        chemicalDeliveryOrder.setStatus((Integer) DeliveryOrderEnum.WAIT_DELIVERY.getValue());
        return page(page, chemicalDeliveryOrder);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean finishById(Account account, Long id, String remark) {
        LmsChemicalDeliveryOrder lcd = getById(id);
        if (lcd.getStatus().equals(DeliveryOrderEnum.FINISH.getValue()) ) {
            return true;
        }
        LmsChemicalDeliveryOrder tempLcd = new LmsChemicalDeliveryOrder();
        tempLcd.setId(lcd.getId());
        tempLcd.setStatus((Integer) DeliveryOrderEnum.FINISH.getValue());
        // 追加备注
        StringBuffer postil = new StringBuffer();
        if (null != lcd.getPostil()) {
            postil.append(lcd.getPostil()).append(" | ");
        }
        postil.append(remark).append("-结束【").append(account.getUserName()).append("】");
        tempLcd.setPostil(postil.toString());

        // 1、设置出库单为结束状态 2、出库单行标记为结束状态
        return super.updateById(tempLcd) && lmsChemicalRelDeliveryService.finishByOrderId(id);
    }
}
