package com.prolog.cs.biz.inbound.controller;

import com.prolog.cs.basic.warehouse.model.BaseWmsWarehouseMst;
import com.prolog.cs.biz.inbound.dao.SupervisionCodeMapper;
import com.prolog.cs.biz.inbound.model.SupervisionCode;
import com.prolog.cs.biz.inbound.remote.BaseWmsWarehouseCaller;
import com.prolog.cs.biz.inbound.service.impl.SupervisionCodeXmlHandler;
import com.prolog.cs.biz.inbound.utils.ObjectUtils;
import com.prolog.framework.bz.common.search.SearchApi;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.exception.BizException;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.framework.utils.AssertUtils;
import com.prolog.framework.utils.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;


/**
 * @Description // TODO
 * @Date 2021-06-03
 */

@Api(tags = "监管码xml导出")
@RestController
@RequestMapping("/supervisionCodeXml")
public class SupervisionCodeXmlController {

	private static Logger log = LoggerFactory.getLogger(SupervisionCodeXmlController.class);

	@Resource
	private SupervisionCodeXmlHandler supervisionCodeXmlHandler;

	@Resource
	private SupervisionCodeMapper mapper;

	@Resource
	private BaseWmsWarehouseCaller baseWmsWarehouseCaller;

	@Resource
	private RedisTemplate redisTemplate;

	@Resource
	private SearchApi searchApi;

	SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");

	@ResponseBody
	@ApiOperation(value = "xml导出", notes = "xml导出，supervisionType：0=入库 1=出库；ids以逗号分隔")
	@GetMapping("/exportXml")
	public void exportXml(@RequestParam Integer supervisionType,@RequestParam String ids, HttpServletResponse response){
		//设置文件的名称和格式
		AssertUtils.notNull(supervisionType, "入参supervisionType不能为空");
		AssertUtils.notNull(ids, "入参ids不能为空");
		BufferedOutputStream buff = null;
		ServletOutputStream outStr = null;
		Integer inorout; // 0-入库 1-出库
		if( supervisionType==0 || supervisionType==1){
			inorout= 0 ;
		}else {
			inorout= 1 ;
		}
		try {
			String[] split = ids.split(",");
			if(split==null || split.length==0){
				throw new BizException("入参为空!");
			}
			List<SupervisionCode> voList = this.mapper.findByIds(SupervisionCode.class, split, null);
			if(voList==null || voList.size()==0){
				throw new BizException("数据为空!");
			}
			String warehouseName="";
			RestMessage<BaseWmsWarehouseMst> itemResultWarehouse = baseWmsWarehouseCaller.warehouse(voList.get(0).getWarehouseId());
			if (itemResultWarehouse.isSuccess() && itemResultWarehouse.getData() != null) {
				warehouseName=itemResultWarehouse.getData().getWarehouseName();

			}
			String srcCode = voList.get(0).getSrcCode();
			response.reset();// 清空输出流
			if(StringUtils.isBlank(warehouseName)){
				throw new BizException("仓库为空，数据异常!");
			}else{
				String fileName=URLEncoder.encode((inorout==0?"IN":"OUT")+
						"_"+warehouseName+"_" + sdf.format(new Date()) + "_" + srcCode + ".xml", "UTF-8");
				response.addHeader("Content-Disposition",fileName);
			}
			Map<String, Map<String, String>> elecCodeMap = new HashMap();
			String beanToXml = supervisionCodeXmlHandler.spellXml(inorout, voList,elecCodeMap);

			response.setCharacterEncoding("UTF-8");
			response.setContentType("application/octet-stream; charset=UTF-8");
			outStr = response.getOutputStream();
			buff = new BufferedOutputStream(outStr);
			buff.write(beanToXml.getBytes("UTF-8"));
			buff.flush();
			buff.close();
			supervisionCodeXmlHandler.batchUpdateBySrcCode(voList.stream().map(SupervisionCode::getSrcCode)
					.collect(Collectors.toList()));
		} catch (Exception e) {
			log.error("exportXml",e);
		} finally {
			try {
				if(buff!=null)
					buff.close();
				if(outStr!=null)
					outStr.close();
			} catch (Exception e) {
				log.error("exportXml",e);
			}
		}
	}

	@ResponseBody
	@ApiOperation(value = "xml全部导出zip", notes = "xml全部导出，supervisionType：0=入库 1=出库；ids以逗号分隔")
	@GetMapping("/exportXmlAll")
	public void exportXmlAll(@RequestParam String warehouseId,@RequestParam String cargoOwnerId,
							 @RequestParam Integer supervisionType,@RequestParam(required = false) String srcCode,
							 HttpServletResponse response) throws Exception {
		BufferedInputStream bufferedInputStream = null;
		ZipOutputStream zipOutputStream = null;
		OutputStream outputStream = null;
		String warehouseName="";
		Integer inorout; // 0-入库 1-出库
		if( supervisionType==0 || supervisionType==1){
			inorout= 0 ;
		}else {
			inorout= 1 ;
		}
		try {
			RestMessage<BaseWmsWarehouseMst> itemResultWarehouse = baseWmsWarehouseCaller.warehouse(warehouseId);
			if (itemResultWarehouse.isSuccess() && itemResultWarehouse.getData() != null) {
				warehouseName=itemResultWarehouse.getData().getWarehouseName();
			}
			Criteria crt = Criteria.forClass(SupervisionCode.class);
			Restriction eq = StringUtils.isBlank(warehouseId) ? null : Restrictions.eq("warehouseId", warehouseId);
			Restriction eq2 = StringUtils.isBlank(cargoOwnerId) ? null : Restrictions.eq("cargoOwnerId", cargoOwnerId);
			Restriction eq3 = ObjectUtils.isNull(supervisionType) ? null : Restrictions.eq("supervisionType", supervisionType);
			Restriction eq4 = ObjectUtils.isNull(srcCode) ? null : Restrictions.eq("srcCode", srcCode);
			Restriction eq5 = Restrictions.isNotNull("srcCode");
			Restriction eq6 = Restrictions.eq("status", 10);
			crt.setRestriction(Restrictions.and(eq, eq2, eq3, eq4, eq5, eq6));
			List<SupervisionCode> voList = this.mapper.findByCriteria(crt);
			String inOrOut = (supervisionType == 0 || supervisionType == 1) ? "IN" : "OUT";
			String preFileName = inOrOut + "_" + warehouseName + "_" + sdf.format(new Date());
			response.reset();
			response.setHeader("Access-Control-Allow-Origin", "*");
			response.setContentType("application/octet-stream; charset=utf-8");
			response.setCharacterEncoding("UTF-8");
			outputStream = response.getOutputStream();
			zipOutputStream = new ZipOutputStream(outputStream);
			if(voList==null || voList.size()==0){
				response.setHeader("Content-Disposition", URLEncoder.encode( "noXmlData.zip","UTF-8"));
				ZipEntry zipEntry = new ZipEntry( "noXmlData.xml");
				zipOutputStream.putNextEntry(zipEntry);
				zipOutputStream.write("<noXmlData>noXmlData<noXmlData>".getBytes("UTF-8"));
				zipOutputStream.flush();
				zipOutputStream.close();
			}else{
				response.setHeader("Content-Disposition", URLEncoder.encode(preFileName + ".zip","UTF-8"));
				List<String> srcCodeList= voList.stream().map(SupervisionCode::getSrcCode).distinct().collect(Collectors.toList());
				Map<String, Map<String, String>> elecCodeMap = new HashMap();
				List<String> subSrcOrderStrList=srcCodeList.subList(0,srcCodeList.size()>1000?1000:srcCodeList.size());
				List<SupervisionCode> srcCodeSubList =voList.stream().filter(p -> subSrcOrderStrList.contains(p.getSrcCode())).collect(Collectors.toList());
				Set supplierSet = srcCodeSubList.stream().filter(t->!StringUtils.isBlank(t.getSupplierId())).map(SupervisionCode::getSupplierId).collect(Collectors.toSet());;
				//请求客户信息
				Set customerSet = srcCodeSubList.stream().filter(t->!StringUtils.isBlank(t.getShipperId())).map(SupervisionCode::getShipperId).collect(Collectors.toSet());;
				try {
					if(supplierSet!=null && supplierSet.size()>0){
						Map<String, Object> queryMap = new HashMap<>();
						queryMap.put("type", "supplier");
						queryMap.put("ids", new ArrayList<>(supplierSet));
						List<Map> searchForMap = searchApi.searchForMap("queryChainElecCode", queryMap);
						for (int i = 0; i < searchForMap.size(); i++) {
							Map map = searchForMap.get(i);
							Map sonMap=new HashMap();
							sonMap.put("code",map.get("code").toString());
							sonMap.put("elecCode",map.get("elecCode")==null?null:map.get("elecCode").toString());
							elecCodeMap.put(map.get("id").toString(), sonMap);
						}
					}
				} catch (Exception e) {
					log.error("随机获取质检操作员接口异常", e);
					//throw new BizException("调用查询服务queryChainElecCode异常");
				}
				try {
					if(customerSet!=null && customerSet.size()>0){
						Map<String, Object> queryMap1 = new HashMap<>();
						queryMap1.put("type", "customer");
						queryMap1.put("ids", new ArrayList<>(customerSet));
						List<Map> searchForMap1 = searchApi.searchForMap("queryChainElecCode", queryMap1);
						for (int i = 0; i < searchForMap1.size(); i++) {
							Map map = searchForMap1.get(i);
							Map sonMap=new HashMap();
							sonMap.put("code",map.get("code").toString());
							sonMap.put("elecCode",map.get("elecCode")==null?null:map.get("elecCode").toString());
							elecCodeMap.put(map.get("id").toString(), sonMap);
						}
					}
				} catch (Exception e) {
					log.error("随机获取质检操作员接口异常", e);
					//throw new BizException("调用查询服务queryChainElecCode异常");
				}
				log.info("supervisionType:"+supervisionType+",文件："+preFileName+",订单数:"+subSrcOrderStrList.size());
				for (int i = 0; i < subSrcOrderStrList.size(); i++) {
					String tempSrcOrderStr=srcCodeList.get(i);
					ZipEntry zipEntry = new ZipEntry(preFileName  + "_"+ tempSrcOrderStr+ ".xml");
					zipOutputStream.putNextEntry(zipEntry);
					List<SupervisionCode> oneOrderList =srcCodeSubList.stream().filter(p -> tempSrcOrderStr.equals(p.getSrcCode())).collect(Collectors.toList());
					String beanToXml = supervisionCodeXmlHandler.spellXml(inorout, oneOrderList, elecCodeMap);
					zipOutputStream.write(beanToXml.getBytes("UTF-8"));
				}
				supervisionCodeXmlHandler.batchUpdateBySrcCode(subSrcOrderStrList);
				zipOutputStream.flush();
				zipOutputStream.close();
			}
		} catch (IOException e) {
			log.error("exportXml",e);
			throw new RuntimeException(e);
		} finally {
			// 关闭流
			try {
				if (null != bufferedInputStream) {
					bufferedInputStream.close();
				}
				if (null != zipOutputStream) {
					zipOutputStream.close();
				}
				if (null != outputStream) {
					outputStream.close();
				}
			} catch (IOException e) {
				log.error("IOException occureds...", e);
			}
		}
	}
}
