package com.sunda.spmswms.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sunda.spmscommon.ResponseResult;
import com.sunda.spmscommon.entity.ZSapOrgClient;
import com.sunda.spmscommon.feign.IFeignServiceCommon;
import com.sunda.spmscommon.mapper.ZSapOrgClientMapper;
import com.sunda.spmswms.dto.WhsSearchDTO;
import com.sunda.spmswms.mapper.WhsReportMapper;
import com.sunda.spmswms.service.IWhsReport;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class WhsReport implements IWhsReport {

    @Autowired
    WhsReportMapper whsReportMapper;
    
    @Autowired
    IFeignServiceCommon iFeignServiceCommon;
    
    @Autowired
    ZSapOrgClientMapper zSapOrgClientMapper;

    /**
     * 按照物料编码,需求单号,箱码,包装单号,采购定单号,送货单号,内部交货单号等查询箱码信息
     * */
    @Override
    public ResponseResult queryBoxInfo(JSONObject queryObj) {
        if(null==queryObj) return ResponseResult.error("Please provide query parmas");
        String boxNote=StringUtils.isEmpty(queryObj.getString("boxNote"))?null:queryObj.getString("boxNote");
        String materialNo=StringUtils.isEmpty(queryObj.getString("materialNo"))?null:queryObj.getString("materialNo");
        String demandNo=StringUtils.isEmpty(queryObj.getString("demandNo"))?null:queryObj.getString("demandNo");
        String packageNote=StringUtils.isEmpty(queryObj.getString("packageNote"))?null:queryObj.getString("packageNote");
        String purchaseNo=StringUtils.isEmpty(queryObj.getString("purchaseNo"))?null:queryObj.getString("purchaseNo");
        String deliveryNoteSap=StringUtils.isEmpty(queryObj.getString("deliveryNoteSap"))?null:queryObj.getString("deliveryNoteSap");
        String srmContractNo=StringUtils.isEmpty(queryObj.getString("srmContractNo"))?null:queryObj.getString("srmContractNo");
        return ResponseResult.success().add("boxInfo",whsReportMapper.queryBoxInfo(boxNote,materialNo,demandNo,packageNote,purchaseNo,deliveryNoteSap,srmContractNo));
    }

    /*出库 -- 贸易货导出 -- 装柜清单*/
    @Override
    public ResponseResult outWHExportM(JSONObject querObj) {
        String packageList=StringUtils.isEmpty(querObj.getString("packageList"))?null:querObj.getString("packageList");
        String cabinetNumber=StringUtils.isEmpty(querObj.getString("cabinetNumber"))?null:querObj.getString("cabinetNumber");
        if(StringUtils.isEmpty(packageList) && StringUtils.isEmpty(cabinetNumber)){
            return ResponseResult.error("packageList and cabinetNumber are all blank");
        }

        return ResponseResult.success().add("outWHExportM",whsReportMapper.outWHExportM(cabinetNumber,packageList));
    }

    /*出库 -- 备件货导出 -- 装柜清单*/
    @Override
    public ResponseResult outWHExportX(JSONObject querObj) {
        String packageList=StringUtils.isEmpty(querObj.getString("packageList"))?null:querObj.getString("packageList");
        String cabinetNumber=StringUtils.isEmpty(querObj.getString("cabinetNumber"))?null:querObj.getString("cabinetNumber");
        if(StringUtils.isEmpty(packageList) && StringUtils.isEmpty(cabinetNumber)){
            return ResponseResult.error("packageList and cabinetNumber are all blank");
        }
        
        return ResponseResult.success().add("outWHExportX",whsReportMapper.outWHExportX(cabinetNumber,packageList));
    }

    @Override
    public ResponseResult inHouseDtlExport(JSONObject queryObj,String goodsType) {
        String werks=StringUtils.isEmpty(queryObj.getString("werks"))?null:queryObj.getString("werks");
        String whsLocationCode=StringUtils.isEmpty(queryObj.getString("whsLocationCode"))?null:queryObj.getString("whsLocationCode");
        String deliveryNoteSap=StringUtils.isEmpty(queryObj.getString("deliveryNoteSap"))?null:queryObj.getString("deliveryNoteSap");
        String startDate=queryObj.getString("startDate");
        String endDate=queryObj.getString("endDate");

        if(StringUtils.isEmpty(werks) || StringUtils.isEmpty(whsLocationCode)){
            return ResponseResult.error("Werks and WhsLocationCode are mandatory required");
        }

        if(StringUtils.isEmpty(startDate) || StringUtils.isEmpty(endDate)){
            return ResponseResult.error("Date period is mandatory required");
        }
        if(goodsType.equals("X")){
            return ResponseResult.success().add("inHouseDtlExportX",whsReportMapper.inHouseDtlExportX(werks,whsLocationCode,startDate,endDate,deliveryNoteSap)) ;
        }else {
            return ResponseResult.success().add("inHouseDtlExportM", whsReportMapper.inHouseDtlExportM(werks, whsLocationCode, startDate, endDate, deliveryNoteSap));
        }
    }

    @Override
    public ResponseResult outHouseDtlExport(JSONObject queryObj,String goodsType) {
        String werks=StringUtils.isEmpty(queryObj.getString("werks"))?null:queryObj.getString("werks");
        String whsLocationCode=StringUtils.isEmpty(queryObj.getString("whsLocationCode"))?null:queryObj.getString("whsLocationCode");
        String packageList=StringUtils.isEmpty(queryObj.getString("packageList"))?null:queryObj.getString("packageList");
        String startDate=queryObj.getString("startDate");
        String endDate=queryObj.getString("endDate");
        if(StringUtils.isEmpty(werks) || StringUtils.isEmpty(whsLocationCode)){
            return ResponseResult.error("Werks and WhsLocationCode are mandatory required");
        }

        if(StringUtils.isEmpty(startDate) || StringUtils.isEmpty(endDate)){
            return ResponseResult.error("Date period is mandatory required");
        }
        if(goodsType.equals("X")){
            return ResponseResult.success().add("outHouseDtlExportX",whsReportMapper.outHouseDtlExportX(werks,whsLocationCode,startDate,endDate,packageList)) ;
        }else {
            return ResponseResult.success().add("outHouseDtlExportM", whsReportMapper.outHouseDtlExportM(werks, whsLocationCode, startDate, endDate, packageList));
        }
    }

	@SuppressWarnings("rawtypes")
	@Override
	public ResponseResult getMaterialStockQtyDifferList(WhsSearchDTO dto) {
		String werks = dto.getWerks();
		String lgort = dto.getWhsLocationCode();
//		String differNum = dto.getDifferNum();
		String goodsType = dto.getGoodsType();
		String displayDiff = dto.getDisplayDiff();
		if (StringUtils.isEmpty(werks)) {
			ResponseResult.error("请求工厂不能为空");
		}
		if (StringUtils.isEmpty(lgort)) {
			ResponseResult.error("仓库编号不能为空");
		}
		String nowDate = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
		// 查询SPMS端的数据
		List<Map<String, Object>> spmsList = new ArrayList<>();
		if (StringUtils.isEmpty(goodsType)) {
			// 查询贸易货数据
			List<Map<String, Object>> tradeStockQtyList = whsReportMapper.selectTradeStockQty(dto);
			// 查询备件货数据
			List<Map<String, Object>> sparePartStockQtyList = whsReportMapper.selectSparePartStockQty(dto);
			spmsList.addAll(tradeStockQtyList);
			spmsList.addAll(sparePartStockQtyList);
		} else if ("M".equals(goodsType)) {
			// 贸易货
			List<Map<String, Object>> tradeStockQtyList = whsReportMapper.selectTradeStockQty(dto);
			spmsList.addAll(tradeStockQtyList);
		} else if ("X".equals(goodsType)) {
			// 备件货
			List<Map<String, Object>> sparePartStockQtyList = whsReportMapper.selectSparePartStockQty(dto);
			spmsList.addAll(sparePartStockQtyList);
		}
		List<Map<String, Object>> returnList = new ArrayList<Map<String, Object>>();
		if (CollectionUtils.isNotEmpty(spmsList)) {
			Map<String, List<Map>> collect = new HashMap<>();
			// 调用接口查询SAP数据
			// 如果前端没有使用模糊查询，就先查询SAP同工厂的数据；如果使用了模糊查询，先查询SPMS的数据再循环查询SAP的数据
			if (StringUtils.isEmpty(dto.getSearchInfo())) {
				JSONObject dataToSap = this.materialStockSendSap(dto);
				// 根据工厂查询对应的SAP Clinet
                List<ZSapOrgClient> clinetList = zSapOrgClientMapper.selectList(new QueryWrapper<ZSapOrgClient>().eq("WERKS", werks));
                if (!CollectionUtils.isEmpty(clinetList)) {
                	JSONObject esbObj = dataToSap.getJSONObject("REQUEST").getJSONObject("ESB_ATTRS");
                	esbObj.put("Target_ID", "SAP-"+clinetList.get(0).getZmandt());
                } else {
                	return ResponseResult.error("工厂："+werks+"未找到对应的SAP Clinet");
                }
				JSONObject message = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSap));
				JSONObject returnDate = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");
				if ("S".equals(returnDate.getString("O_TYPE"))){
					JSONArray jsonArray = returnDate.getJSONArray("IT_STOCK");
					if (jsonArray.size() > 0) {
						List<Map> javaList = jsonArray.toJavaList(Map.class);
						collect = javaList.stream().collect(Collectors.groupingBy(e -> e.get("WERKS")+"_"+e.get("LGORT")+"_"+e.get("MATNR")));
					}
				}
			}
			for (int i = 0; i < spmsList.size(); i++) {
				// 汇总数量
				BigDecimal allNumber = BigDecimal.ZERO;
				// 汇总修正量
				BigDecimal allUpdateNumber = BigDecimal.ZERO;
				Map<String, Object> map = spmsList.get(i);
				String key = map.get("werks")+"_"+map.get("whsLocationCode")+"_"+map.get("materialNo");
				if (StringUtils.isEmpty(dto.getSearchInfo())) {
					List<Map> diffList = collect.get(key);
					if (CollectionUtils.isNotEmpty(diffList)) {
						for (Map mm : diffList) {
							if (StringUtils.isNotEmpty(mm.get("LABST").toString())) {
								allNumber = allNumber.add(new BigDecimal(mm.get("LABST").toString()));
							}
							if (StringUtils.isNotEmpty(mm.get("CORRQTY").toString())) {
								allUpdateNumber = allUpdateNumber.add(new BigDecimal(mm.get("CORRQTY").toString()));
							}
						}
					}
				} else {
					// 模糊查询根据物料编码查询SAP库存数量
					dto.setSearchInfo(map.get("materialNo").toString());
					JSONObject dataToSap = this.materialStockSendSap(dto);
					// 根据工厂查询对应的SAP Clinet
	                List<ZSapOrgClient> clinetList = zSapOrgClientMapper.selectList(new QueryWrapper<ZSapOrgClient>().eq("WERKS", werks));
	                if (!CollectionUtils.isEmpty(clinetList)) {
	                	JSONObject esbObj = dataToSap.getJSONObject("REQUEST").getJSONObject("ESB_ATTRS");
	                	esbObj.put("Target_ID", "SAP-"+clinetList.get(0).getZmandt());
	                } else {
	                	return ResponseResult.error("工厂："+werks+"未找到对应的SAP Clinet");
	                }
					JSONObject message = JSONObject.parseObject(iFeignServiceCommon.sendRestToSapCommon(dataToSap));
					JSONObject returnDate = message.getJSONObject("RESPONSE").getJSONObject("RETURN_DATA");
					if ("S".equals(returnDate.getString("O_TYPE"))){
						JSONArray jsonArray = returnDate.getJSONArray("IT_STOCK");
						if (jsonArray.size() > 0) {
							List<Map> javaList = jsonArray.toJavaList(Map.class);
							collect = javaList.stream().collect(Collectors.groupingBy(e -> e.get("WERKS")+"_"+e.get("LGORT")+"_"+e.get("MATNR")));
							List<Map> diffList = collect.get(key);
							if (CollectionUtils.isNotEmpty(diffList)) {
								for (Map mm : diffList) {
									if (StringUtils.isNotEmpty(mm.get("LABST").toString())) {
										allNumber = allNumber.add(new BigDecimal(mm.get("LABST").toString()));
									}
									if (StringUtils.isNotEmpty(mm.get("CORRQTY").toString())) {
										allUpdateNumber = allUpdateNumber.add(new BigDecimal(mm.get("CORRQTY").toString()));
									}
								}
							}
						}
					}
				}
				// sap库存量
				map.put("labst", allNumber.setScale(3));
				// SPMS修正量
				map.put("corrqty", allUpdateNumber.setScale(3));
				// SPMS库存量
				if (StringUtils.isEmpty(map.get("availableQty").toString())) {
					map.put("availableQty", "0");
				}
				BigDecimal availableQty = new BigDecimal(map.get("availableQty").toString()).setScale(3);
				// SPMS&SAP库存差异：SAP库存量-(SPMS库存量+SPMS修正量)
				BigDecimal diffQty = new BigDecimal(map.get("labst").toString()).subtract(availableQty.add(allUpdateNumber.setScale(3)));
				map.put("availableQty", availableQty);
				map.put("diffQty", diffQty);
				// 未提交SAP库存量：总数量-SPMS库存量
				if (StringUtils.isEmpty(map.get("quantity").toString())) {
					map.put("quantity", "0.000");
				}
				BigDecimal noPushQty = new BigDecimal(map.get("quantity").toString()).subtract(new BigDecimal(map.get("availableQty").toString())).setScale(3, BigDecimal.ROUND_HALF_UP);
				map.put("noPushQty", noPushQty);
				// 待复查库存差异：SPMS库存量-SAP库存量-未提交SAP库存量
				BigDecimal diffReviewQty = new BigDecimal(map.get("availableQty").toString()).subtract(new BigDecimal(map.get("labst").toString())).subtract(new BigDecimal(map.get("noPushQty").toString()));
				map.put("diffReviewQty", diffReviewQty.setScale(3));
				// 查询日期
				map.put("nowDate", nowDate);
				// 是否显示差异
				if ("1".equals(displayDiff)) {
					if (BigDecimal.ZERO.compareTo(new BigDecimal(map.get("diffQty").toString())) != 0) {
						returnList.add(map);
					}
				} else {
					returnList.add(map);
				}
//				if (StringUtils.isNotEmpty(differNum)) {
//					if (new BigDecimal(map.get("diffQty").toString()).compareTo(new BigDecimal(differNum)) >= 0) {
//						returnList.add(map);
//					}
//				} else {
//					returnList.add(map);
//				}
			}
		}
		return ResponseResult.success().add("returnList", returnList);
	}

	private JSONObject materialStockSendSap(WhsSearchDTO dto) {
		JSONObject doc = new JSONObject();
        JSONObject REQUEST = new JSONObject();
        JSONObject ESB_ATTRS = new JSONObject();
        JSONObject REQUEST_DATA = new JSONObject();

        ESB_ATTRS.put("App_ID", "SPMS");
        ESB_ATTRS.put("Application_ID", "00020000000002");
        ESB_ATTRS.put("Transaction_ID", UUID.randomUUID().toString());
        
        String werks = dto.getWerks();
		String lgort = dto.getWhsLocationCode();
		String materialNo = dto.getSearchInfo();
        JSONObject head = new JSONObject();
        head.put("I_WERKS", werks);
        head.put("I_LGORT", lgort);
        head.put("I_MATNR", materialNo);

        REQUEST_DATA.put("fileds", head);
        REQUEST_DATA.put("Operation", "Z_SPMS_READ_STOCK");
        REQUEST_DATA.put("Type", "SPMS_READ_STOCK");

        REQUEST.put("ESB_ATTRS", ESB_ATTRS);
        REQUEST.put("REQUEST_DATA", REQUEST_DATA);

        doc.put("REQUEST", REQUEST);
        return doc;
	}

	@Override
	public ResponseResult getBoxInfoList(WhsSearchDTO dto) {
		Integer pageNo = dto.getPageNo();
		Integer pageSize = dto.getPageSize();
		Page<Map<String, Object>> pages = new Page<>(pageNo, pageSize);
		List<Map<String, Object>> pageData = whsReportMapper.findBoxInfo(pages, dto);
		if (CollectionUtils.isNotEmpty(pageData)) {
			String nowDate = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
			for (Map<String, Object> map : pageData) {
				map.put("nowDate", nowDate);
			}
		}
		pages.setRecords(pageData);
		return ResponseResult.success().add("boxInfo", pages);
	}

	@Override
	public ResponseResult getSapDeliveryNoteAndOtherTask(WhsSearchDTO dto) {
		Integer pageNo = dto.getPageNo();
		Integer pageSize = dto.getPageSize();
		Page<Map<String, Object>> pages = new Page<>(pageNo, pageSize);
		
		List<Map<String, Object>> pageData = whsReportMapper.findSapDeliveryNoteAndOtherTaskData(pages, dto);
		if (CollectionUtils.isNotEmpty(pageData)) {
			for (int j = 0; j < pageData.size(); j++) {
				Map<String, Object> map = pageData.get(j);
				if (map.get("goodsType") != null && "M".equals(map.get("goodsType").toString())) {
					if (map.get("storageCode") != null) {
						String storageCode = map.get("storageCode").toString();
						if (storageCode.contains("storageNo")) {
							List<Map> storageList = JSONArray.parseArray(storageCode, Map.class);
							if (storageList.size() > 1) {
								for (int i = 0; i < storageList.size(); i++) {
									Map<String, Object> insertMap = map;
									insertMap.put("storageCode", storageList.get(i).get("storageNo"));
									insertMap.put("quantity", storageList.get(i).get("unitValue"));
									// 体积
									BigDecimal vol = BigDecimal.ZERO;
									if (storageList.get(i).get("qty") != null && map.get("volume") != null) {
										vol = new BigDecimal(storageList.get(i).get("qty").toString()).multiply(new BigDecimal(map.get("volume").toString()));
									}
									insertMap.put("volume", vol);
									pageData.add(insertMap);
								}
								map.put("storageCode", storageList.get(0).get("storageNo"));
								map.put("quantity", storageList.get(0).get("unitValue"));
								// 体积
								BigDecimal vol = BigDecimal.ZERO;
								if (storageList.get(0).get("qty") != null && map.get("volume") != null) {
									vol = new BigDecimal(storageList.get(0).get("qty").toString()).multiply(new BigDecimal(map.get("volume").toString()));
								}
								map.put("volume", vol);
							} else {
								if (map.get("quantity") != null && map.get("volume") != null && map.get("numerator") != null && map.get("denominator") != null) {
									// 将销售数量转换基本单位数量来计算体积
									BigDecimal multiply = new BigDecimal(map.get("quantity").toString()).multiply(new BigDecimal(map.get("numerator").toString())).divide(new BigDecimal(map.get("denominator").toString()), 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(map.get("volume").toString()));
									map.put("volume", multiply);
								}
								map.put("storageCode", storageList.get(0).get("storageNo"));
							}
						} else {
							if (map.get("quantity") != null && map.get("volume") != null && map.get("numerator") != null && map.get("denominator") != null) {
								// 将销售数量转换基本单位数量来计算体积
								BigDecimal multiply = new BigDecimal(map.get("quantity").toString()).multiply(new BigDecimal(map.get("numerator").toString())).divide(new BigDecimal(map.get("denominator").toString()), 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(map.get("volume").toString()));
								map.put("volume", multiply);
							}
						}
					}
				} else if (map.get("goodsType") == null) {
					// 赠品入库、卸货入库计算体积
					if (map.get("quantity") != null && map.get("volume") != null && map.get("numerator") != null && map.get("denominator") != null) {
						// 将销售数量转换基本单位数量来计算体积
						BigDecimal multiply = new BigDecimal(map.get("quantity").toString()).multiply(new BigDecimal(map.get("numerator").toString())).divide(new BigDecimal(map.get("denominator").toString()), 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(map.get("volume").toString()));
						map.put("volume", multiply);
					}
				}
			}
		}
		pages.setRecords(pageData);
		return ResponseResult.success().add("dataList", pages);
	}

	@Override
	public ResponseResult getReconciliationReport(WhsSearchDTO dto) {
		Integer pageNo = dto.getPageNo();
		Integer pageSize = dto.getPageSize();
		Page<Map<String, Object>> pages = new Page<>(pageNo, pageSize);
		
		List<Map<String, Object>> pageData = whsReportMapper.findReconcilitionList(pages, dto);
		if (CollectionUtils.isNotEmpty(pageData)) {
			for (Map<String, Object> map : pageData) {
				
				
				
			}
			
			
		}
		
		pages.setRecords(pageData);
		return ResponseResult.success().add("dataList", pages);
	}

}
