package com.cim.idm.service.Impl;

import com.alibaba.fastjson.JSON;
import com.cim.idm.constants.delivery.DeliveryStateEnums;
import com.cim.idm.constants.delivery.DeliveryTypeEnums;
import com.cim.idm.constants.receive.IsBatchEnums;
import com.cim.idm.constants.receive.ReceiveTypeEnums;
import com.cim.idm.dao.DeliveryDao;
import com.cim.idm.exception.GlobalException;
import com.cim.idm.framework.IDMFrameServiceProxy;
import com.cim.idm.framework.data.EventInfo;
import com.cim.idm.framework.util.time.TimeStampUtil;
import com.cim.idm.model.dto.PageDto;
import com.cim.idm.model.dto.PurchaseDto;
import com.cim.idm.model.dto.delivery.*;
import com.cim.idm.model.po.delivery.MaterialDelivery;
import com.cim.idm.model.po.delivery.MaterialDeliveryReceive;
import com.cim.idm.model.po.MaterialReceiveRequest;
import com.cim.idm.model.vo.DeliveryReceiveDetailVo;
import com.cim.idm.model.vo.MaterialReceiveRequestVo;
import com.cim.idm.model.vo.ReceiveDetailVo;
import com.cim.idm.mwmsextend.materialpacking.service.MaterialPackingServiceImpl;
import com.cim.idm.service.IDeliveryService;
import com.cim.idm.utils.AjaxResult;
import com.cim.idm.utils.EventInfoUtil;
import com.cim.idm.wmsextend.generic.GenericServiceProxy;
import com.cim.idm.wmsextend.generic.errorHandler.CustomException;
import com.cim.idm.wmspackage.material.MaterialServiceProxy;
import com.cim.idm.wmspackage.material.management.data.MaterialSpec;
import com.cim.idm.wmspackage.material.management.data.MaterialSpecKey;
import com.cim.idm.wmspackage.materialpacking.management.info.CreateInfo;
import com.cim.idm.wmspackage.name.NameServiceProxy;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.page.PageMethod;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class DeliveryServiceImpl implements IDeliveryService {

    @Resource
    private DeliveryDao deliveryDao;

    @Override
    @Transactional
    public int createDelivery(DeliveryDto dto) {
        // 添加到库单关系
        List<DeliveryRelationDto> res = new ArrayList<>();
        for (DeliveryRelationDto item : dto.getReceiveList()) {
            // 数量大于 0
            if (Objects.nonNull(item.getDeliveryNum()) && item.getDeliveryNum() > 0) {
                // 到库单号
                item.setDeliveryName(dto.getDeliveryName());
                res.add(item);
            }
        }
        if (res.isEmpty()) {
            throw new GlobalException("无可用的物料");
        }
        if (deliveryDao.createRelation(res) <= 0) {
            throw new GlobalException("添加到库单关系失败");
        }
        //更新采购订单行项的已入库数量
        for (DeliveryRelationDto re : res) {
            if (deliveryDao.updateMaterialReceiveRequestDetailQty(re) <= 0){
                throw new GlobalException("更新采购单入库数量失败");
            }
        }


        // 添加到库单
        return deliveryDao.createDelivery(dto, DeliveryStateEnums.CREATE.getCode());
    }

    @Override
    public PageInfo<MaterialReceiveRequestVo> getReceiveList(PageDto dto) {
        PageMethod.startPage(dto.getPageNum(), dto.getPageSize());
        PurchaseDto purchaseDto = JSON.toJavaObject(dto.getParams(), PurchaseDto.class);
        // 区分是辅材还是批次
        String isBatch = IsBatchEnums.N.getCode();
        if (purchaseDto.getDeliveryType().equals(DeliveryTypeEnums.BATCH.getCode())) {
            isBatch = IsBatchEnums.Y.getCode();
        }
        return new PageInfo<>(deliveryDao.getReceiveList(purchaseDto, ReceiveTypeEnums.getPurchase(), isBatch));
    }

    @Override
    public ReceiveDetailVo getStoreDetail(String documentName, String siteName, List<String> nameList, String deliveryName) {
        ReceiveDetailVo receiveDetailVo = new ReceiveDetailVo();
        // 采购单明细
        List<Map<String, Object>> storeDetail = deliveryDao.getStoreDetail(siteName, nameList, ReceiveTypeEnums.getPurchase(), deliveryName);
        receiveDetailVo.setStoreDetail(storeDetail);
        // 批次
        List<Map<String, Object>> storeCharge = deliveryDao.getStoreCharge(siteName, documentName);
        receiveDetailVo.setStoreCharge(storeCharge);
        return receiveDetailVo;
    }

    @Override
    public List<Map<String, Object>> getMaterialDetail(String documentName, String siteName, List<String> nameList, String deliveryName) {
        return deliveryDao.getMaterialDetail(siteName, nameList, ReceiveTypeEnums.getPurchase(), deliveryName);
    }

    @Override
    public MaterialDelivery getByKey(StoreDetailDto storeDetailDto) {
        return deliveryDao.getByKey(storeDetailDto);
    }

    @Override
    public MaterialReceiveRequest getReceiveByKey(StoreDetailDto storeDetailDto) {
        return deliveryDao.getReceiveByKey(storeDetailDto);
    }

    @Override
    public List<MaterialDeliveryReceive> getRelByDelivery(StoreDetailDto storeDetailDto) {
        return deliveryDao.getRelByDelivery(storeDetailDto);
    }

    @Override
    public List<MaterialReceiveRequest> getReceiveByDelivery(StoreDetailDto storeDetailDto) {
        return deliveryDao.getReceiveByDelivery(storeDetailDto);
    }

    @Override
    public List<DeliveryReceiveDetailVo> getReceiveByMaterialSpec(String documentName, String materialSpec, Boolean isDelivery) {
        List<DeliveryReceiveDetailVo> voList;
        if (Boolean.TRUE.equals(isDelivery)) {
            // 到货单
            voList = deliveryDao.getDeliveryByMaterialSpec(documentName, materialSpec);
        } else {
            voList = deliveryDao.getReceiveByMaterialSpec(documentName, materialSpec);
        }
        return voList;
    }

    @Override
    public List<DeliveryReceiveDetailVo> getReceiveDetail(List<String> nameList) {
        return deliveryDao.getReceiveDetail(nameList);
    }

    @Override
    public List<DeliveryReceiveDetailVo> getDeliveryReceiveDetail(List<String> nameList) {
        return deliveryDao.getDeliveryReceiveDetail(nameList);
    }

    @Override
    public PageInfo<MaterialDelivery> getDeliveryList(PageDto dto) {
        PageMethod.startPage(dto.getPageNum(), dto.getPageSize());
        DeliveryListDto deliveryListDto = JSON.toJavaObject(dto.getParams(), DeliveryListDto.class);
        return new PageInfo<>(deliveryDao.getDeliveryList(deliveryListDto));
    }

    @Override
    @Transactional
    public int delDelivery(DeliveryDelDto deliveryDelDto) {
        // 移除到货单关系
        if (deliveryDao.delDeliveryRel(deliveryDelDto) <= 0) {
            throw new GlobalException("删除到货单关系失败");
        }
        // 移除到货单
        return deliveryDao.delDelivery(deliveryDelDto);
    }

    @Override
    public int editDelivery(DeliveryEditDto deliveryEditDto) {
        return deliveryDao.editDelivery(deliveryEditDto);
    }

    @Override
    public ReceiveDetailVo getDeliveryStoreDetail(String documentName, String siteName, List<String> nameList, String deliveryName) {
        ReceiveDetailVo receiveDetailVo = new ReceiveDetailVo();
        // 采购单明细
        //List<Map<String, Object>> storeDetail = deliveryDao.getStoreDetail(siteName, nameList, ReceiveTypeEnums.getPurchase(), deliveryName);
        List<Map<String, Object>> storeDetail = deliveryDao.getDeliveryStoreDetail(siteName, nameList, ReceiveTypeEnums.getPurchase(), deliveryName);
        receiveDetailVo.setStoreDetail(storeDetail);
        // 批次
        List<Map<String, Object>> storeCharge = deliveryDao.getStoreChargeSort(siteName, documentName);
        receiveDetailVo.setStoreCharge(storeCharge);
        return receiveDetailVo;
    }

    @Override
    public void auxiliaryDeliveryStockIn(String siteName, EventInfo eventInfo, String commitDate, String deliveryName, LinkedHashMap<String, String> materialPackingInfoMap) throws Exception {
        Iterator its = materialPackingInfoMap.entrySet().iterator();
        //创建抬头文本
        String receiveAct = GenerateReceiveAct(siteName, "NoPO");
        String specName = "";
        SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        List<CreateInfo> listMaterialPacking = new ArrayList<CreateInfo>();
        //创建批次
        while (its.hasNext()) {
            Map.Entry entry = (Map.Entry) its.next();
            Map boxInfo = (Map) entry.getValue();
            String erpFactory = (String) boxInfo.get("ERPFACTORY");
            String erpLocation = (String) boxInfo.get("ERPLOCATION");
            String LOCATIONNAME = (boxInfo.get("LOCATIONNAME") == null || "null".equals(boxInfo.get("LOCATIONNAME").toString())) ? "" : boxInfo.get("LOCATIONNAME").toString();
            String materialSpecName = (String) boxInfo.get("MATERIALSPECNAME");
            String MATERIALUNITDESC = (String) boxInfo.get("MATERIALUNITDESC");
            String materialUnit = (String) boxInfo.get("MATERIALUNIT");
            String REQUESTQUANTITY = (String) boxInfo.get("REQUESTQUANTITY").toString();
            String RECEIVEDQUANTITY = (String) boxInfo.get("RECEIVEDQUANTITY").toString();
            String ThisAcceptNumber = boxInfo.get("THISACCEPTNUMBER").toString();
            String supplierName = boxInfo.get("SUPPLIERNO").toString();
            String locationName = boxInfo.get("LOCATIONNAME").toString();
            String expirationDay = "";
            if ("0".equals(ThisAcceptNumber)) {
                continue;
            }
            String makeDate = boxInfo.get("MakeDate") == null ? TimeStampUtil.getCurrentTime("yyyy-MM-dd HH:mm:ss") : boxInfo.get("MakeDate").toString();
            String sdkid = (String) boxInfo.get("SDK_ID");
            //5、查询物料是否启用批次
            String queryIsBatchSql = "SELECT CASE WHEN m.IS_BATCH  = 'Y' THEN '是' WHEN m.IS_BATCH  = '是' THEN '是' ELSE '否'  END AS REPLACED_VALUE ,DECODE(m.IQCFLAG,'Y','是','否')  IQCFLAG, PHASE,  FROM MATERIALSPEC m WHERE m.MATERIALSPECNAME =:MATERIALSPECNAME";
            Map<String, Object> isBatchParmsMap = new HashMap<String, Object>();
            isBatchParmsMap.put("MATERIALSPECNAME", materialSpecName);
            List<Map<String, Object>> isBatchList = IDMFrameServiceProxy.getSqlTemplate().queryForList(queryIsBatchSql, isBatchParmsMap);
            MaterialSpecKey materialSpecKey = new MaterialSpecKey();
            materialSpecKey.setMaterialSpecName(materialSpecName);
            materialSpecKey.setSiteName(siteName);
            MaterialSpec materialSpec = MaterialServiceProxy.getMaterialSpecService().selectByKey(materialSpecKey);
            if (null == isBatchList || isBatchList.isEmpty() || null == materialSpec || null == materialSpec.getKey()){
                AjaxResult.me().setMessage("物料编码：" + materialSpecName + "主数据信息不存在").setErrorCode(400);
            } else {
                String isBatch = isBatchList.get(0).get("REPLACED_VALUE").toString();
                String iqcFlag = isBatchList.get(0).get("IQCFLAG").toString();
                String phase = isBatchList.get(0).get("PHASE").toString();
                String materialType = materialSpec.getMaterialType();
                // 获取单据详情
                List<DeliveryReceiveDetailVo> receiveByMaterialSpec = getReceiveByMaterialSpec(deliveryName, materialSpecName, true);
                if (!receiveByMaterialSpec.isEmpty()) {
                    for (DeliveryReceiveDetailVo vo : receiveByMaterialSpec) {
                        //创建抬头文本DETAIL
                        //更新MATERIALRECEIVEREQUESTDETAIL数量
                        //CreateMaterialReceiveRequestAct(eventInfo, "SDK", vo.getReceiveRequestName(), vo.getReceiveRequestDetailName(), MAKEDATE, receiveAct, "NoPO", ThisAcceptNumber, MATERIALSPECNAME);
                        //6、创建标签
                        try {
                            List<String> boxId = MaterialPackingServiceImpl.generateBoxID("LabelId", siteName,"1", makeDate,"WL",erpFactory);
                            for (int i = 0; i < boxId.size(); i++) {
                                //插入MATERIALPACKING
                                CreateInfo materialPacking = new CreateInfo();
                                String newBoxId = materialSpecName + "|1|" + phase + "|" + specName + "|" + boxId.get(i) + "|" + makeDate.replace("-", "").substring(0, 8) + "|" + materialUnit + "|" + ThisAcceptNumber;
                                materialPacking.setMaterialPackingName(newBoxId);
                                materialPacking.setSiteName(siteName);
                                materialPacking.setContentMaterialType("");
                                materialPacking.setMaterialPackingType("Box");
                                Map<String, Object> bindMap = new HashMap<String, Object>();
                                bindMap.put("materialQuantity", ThisAcceptNumber);
                                bindMap.put("materialCreateQuantity", ThisAcceptNumber);
                                bindMap.put("packingState", "Created");// 标记Box是刚创建的
                                bindMap.put("materialType", materialType);
                                bindMap.put("materialSpecName", materialSpecName);
                                bindMap.put("stockState", "Created");
                                bindMap.put("holdState", "N");
                                bindMap.put("areaName", "");
                                bindMap.put("createUser", eventInfo.getEventUser());
                                bindMap.put("createTime", eventInfo.getEventTime());
                                bindMap.put("ReceiveTime", eventInfo.getEventTime());
                                bindMap.put("ReceiveUser", eventInfo.getEventUser());
                                bindMap.put("receiveRequestName", deliveryName);
                                bindMap.put("receiveRequestDetailName","");
                                bindMap.put("SDK_ID", sdkid);
                                if(expirationDay==null||expirationDay.equals(""))
                                {
                                    if(materialSpec.getExpirationDay()>0)
                                    {
                                        Date endTime = sDateFormat.parse(makeDate);
                                        Calendar rightNow = Calendar.getInstance();
                                        rightNow.setTime(endTime);
                                        if(siteName.equals("TM1"))
                                        {
                                            rightNow.add(Calendar.MONTH, materialSpec.getExpirationDay());
                                            rightNow.set(Calendar.DAY_OF_MONTH,rightNow.get(Calendar.DAY_OF_MONTH)-1);
                                        }
                                        else{
                                            rightNow.add(Calendar.MONTH, materialSpec.getExpirationDay());
                                        }
                                        Date dt1 = rightNow.getTime();
                                        expirationDay = sDateFormat.format(dt1);
                                    }
                                    else
                                    {
                                        Date endTime=sDateFormat.parse(makeDate);
                                        Calendar rightNow = Calendar.getInstance();
                                        rightNow.setTime(endTime);
                                        rightNow.add(Calendar.MONTH, 48);
                                        Date dt1 = rightNow.getTime();
                                        expirationDay = "2099-12-31 00:00:00";

                                        //endTime.add(Calendar.MONTH, materialSpec.getExpirationDay());
                                        //endTime = (endTime).(materialSpec.getExpirationDay());
                                    }
                                    //endTime.add(Calendar.MONTH, materialSpec.getExpirationDay());
                                    //endTime = (endTime).(materialSpec.getExpirationDay());
                                }


                                //this.txtEndTime.Text = dt.ToString("yyyy年MM月dd日", System.Globalization.DateTimeFormatInfo.InvariantInfo);
                                bindMap.put("makeDate", makeDate);
                                bindMap.put("expiringDate", expirationDay.substring(0,expirationDay.indexOf(" "))+" 00:00:00");
                                bindMap.put("receiveActNo", receiveAct);
                                bindMap.put("reasonCodeType", "");
                                bindMap.put("reasonCode", "");
                                bindMap.put("erpLocation", erpLocation);
                                bindMap.put("erpFactory", erpFactory);
                                bindMap.put("stockInType", "");
                                bindMap.put("unit", materialUnit);
                                if ("是".equals(isBatch)) {
                                    bindMap.put("charge", boxId.get(i));
                                }
                                if ("否".equals(iqcFlag)) {
                                    bindMap.put("oqaResultState", GenericServiceProxy.getConstantMap().OQA_State_End);
                                    bindMap.put("oqaResult","OK");
                                    bindMap.put("packingGrade", "OK");
                                } else {
                                    bindMap.put("oqaResultState",GenericServiceProxy.getConstantMap().OQA_State_Pre);
                                }
                                bindMap.put("phase", phase);
                                //bindMap.put("supplierCharge", supplierCharge);
                                bindMap.put("supplierName", supplierName);
                                bindMap.put("npFlag", "");
                                bindMap.put("locationName", locationName);
                                materialPacking.setUserColumns(bindMap);
                                listMaterialPacking.add(materialPacking);
                                //插入MATERIALPACKINGSUB
                                String insertSql = "INSERT INTO MATERIALPACKINGSUB T (T.MATERIALPACKINGNAME,T.RECEIVEREQUESTNAME,T.RECEIVEREQUESTDETAILNAME,T.QTY) "
                                        + "VALUES (:MATERIALPACKINGNAME, :RECEIVEREQUESTNAME,:RECEIVEREQUESTDETAILNAME,:QTY)";
                                Map<String, Object> hashMap2 = new HashMap<String,Object> ();
                                hashMap2.put("MATERIALPACKINGNAME", newBoxId);
                                hashMap2.put("RECEIVEREQUESTNAME", deliveryName);
                                hashMap2.put("RECEIVEREQUESTDETAILNAME", "");
                                hashMap2.put("QTY", ThisAcceptNumber);
                                IDMFrameServiceProxy.getSqlTemplate().update(insertSql, hashMap2);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
                //SAP过账
                //更新物料凭证
                //插入BS_MATERIALPACKINGUNDOINFO
                //UPDATE数量 MATERIALPACKING
                //UPDATE 状态 RECEIVEREQUESTNAME
            }
        }
    }

    public static String GenerateReceiveAct( String siteName, String actType) throws CustomException {
        // 获取系统当前时间
        Calendar c = Calendar.getInstance();
        SimpleDateFormat f = new SimpleDateFormat("yyyyMMdd");
        List<String> args = new ArrayList<String>();
        String actType1 = "";
        if (actType.equals("Normal") || actType.equals("Manual") || actType.equals("NoPO")) {
            actType1 = "R";
        } else if (actType.equals("Refund") || actType.equals("WO") || actType.equals("POOEM")
                || actType.equals("ManualT")||actType.equals("MES")||actType.equals("MESRefund")) {
            actType1 = "T";
        }
        args.add(siteName);
        args.add(actType1);
        args.add(f.format(c.getTime()));
        String ReceiveRequestActNo;
        try {
            ReceiveRequestActNo = NameServiceProxy.getNameRuleDefService().generateName("ReceiveActNo", args, 1).get(0);
        } catch (Throwable e) {
            args = new ArrayList<String>();
            args.add(siteName);
            args.add(actType);
            args.add(f.format(c.getTime()));
            ReceiveRequestActNo = NameServiceProxy.getNameRuleDefService().generateName("ReceiveActNo", args, 1).get(0);
            return ReceiveRequestActNo;
        }
        return ReceiveRequestActNo;
    }
}
