package com.emergency.avenue.storage.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.druid.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.emergency.avenue.admin.api.entity.SysDept;
import com.emergency.avenue.admin.api.entity.SysDictItem;
import com.emergency.avenue.admin.api.entity.SysTreeDict;
import com.emergency.avenue.admin.mapper.SysTreeDictMapper;
import com.emergency.avenue.admin.service.SysDeptService;
import com.emergency.avenue.admin.service.SysDictItemService;
import com.emergency.avenue.common.core.util.R;
import com.emergency.avenue.common.security.service.AvenueUser;
import com.emergency.avenue.common.security.util.SecurityUtils;
import com.emergency.avenue.storage.api.entity.OutboundInfo;
import com.emergency.avenue.storage.api.entity.OutboundMaterialInfo;
import com.emergency.avenue.storage.api.entity.OutboundStatus;
import com.emergency.avenue.storage.api.request.OutboundInfoRequest;
import com.emergency.avenue.storage.api.response.OutbountInfoResponse;
import com.emergency.avenue.storage.api.vo.OutboundExcel;
import com.emergency.avenue.storage.mapper.OutboundMapper;
import com.emergency.avenue.storage.mapper.OutboundMaterialMapper;
import com.emergency.avenue.storage.mapper.OutboundStatusMapper;
import com.emergency.avenue.storage.service.OutboundMaterialService;
import com.emergency.avenue.storage.util.MyFileUtil;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class OutboundMaterialServiceImpl extends ServiceImpl<OutboundMaterialMapper, OutboundMaterialInfo> implements OutboundMaterialService {

	private final OutboundMaterialMapper outboundMaterialMapper;

	private final OutboundStatusMapper outboundStatusMapper;

	private final OutboundMapper outboundMapper;

	private final SysTreeDictMapper sysTreeDictMapper;

	private final SysDeptService sysDeptService;

	private final SysDictItemService sysDictItemService;

	@Override
	public R<Map<Object, Object>> listMap(Integer id) {
		Map<Object, Object> objectObjectHashMap = new HashMap<>();
		OutboundInfo outboundInfo = outboundMapper.selectById(id);
		List<OutboundMaterialInfo> outboundMaterialInfos = outboundMaterialMapper.selectList(Wrappers.<OutboundMaterialInfo>query().lambda().eq(OutboundMaterialInfo::getOutboundId, id));
		List<SysTreeDict> orderDictList = sysTreeDictMapper.getOrderDictList(1);
		Map<String, String> collect = orderDictList.stream().collect(Collectors.toMap(SysTreeDict::getId, SysTreeDict::getName));
		for (OutboundMaterialInfo outboundMaterialInfo:outboundMaterialInfos){
			outboundMaterialInfo.setMaterialGroup(collect.get(outboundMaterialInfo.getMaterialGroup()));
			outboundMaterialInfo.setMaterialType(collect.get(outboundMaterialInfo.getMaterialType()));
			outboundMaterialInfo.setMaterialName(collect.get(outboundMaterialInfo.getMaterialName()));
			outboundMaterialInfo.setUnit(collect.get(outboundMaterialInfo.getUnit()));
		}
		objectObjectHashMap.put("outboundMaterial",outboundMaterialInfos);
		QueryWrapper<OutboundStatus> objectQueryWrapper = new QueryWrapper<>();
		objectQueryWrapper.lambda().eq(OutboundStatus::getOutboundId,id).orderByAsc(OutboundStatus::getAuditingTime);
		List<OutboundStatus> outboundStatus = outboundStatusMapper.selectList(objectQueryWrapper);
		Map<String, String> deptMap = sysDeptService.list(Wrappers.<SysDept>lambdaQuery())
				.stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getAbbreviationName));
		outboundStatus.forEach(outboundStatus1 ->outboundStatus1.setWarehouse(deptMap.get(outboundStatus1.getDeptId())));
		objectObjectHashMap.put("outboundStatus",outboundStatus);
		objectObjectHashMap.put("deptId",outboundInfo.getDeptId());
		objectObjectHashMap.put("warehouse",outboundInfo.getWarehouse());
		return R.ok(objectObjectHashMap);
	}

	@Override
	@Transactional
	public R saveOutboundStatus(OutboundStatus outboundStatus) {
		AvenueUser user = SecurityUtils.getUser();
		String deptType = SecurityUtils.getUser().getDeptType();
		if(outboundStatus.getAudi().equals("0")) {
			if (deptType.equals("2")) {
				outboundStatus.setStatus("3");
			}else if (deptType.equals("1")){
				outboundStatus.setStatus("5");
			}
		}else {
			if (deptType.equals("2")) {
				outboundStatus.setStatus("4");
			}else if (deptType.equals("1")){
				outboundStatus.setStatus("6");
			}
		}
		outboundStatusMapper.updatebyIdAndisInvalid(outboundStatus.getOutboundId());
		OutboundInfo outboundInfo = new OutboundInfo();
		outboundInfo.setStatus(outboundStatus.getStatus());
		outboundInfo.setOutboundId(Integer.parseInt(outboundStatus.getOutboundId()));
		outboundMapper.updateById(outboundInfo);
		outboundStatus.setAuditingTime(LocalDateTime.now());
		outboundStatus.setDeptId(user.getDeptId());
		outboundStatus.setUserId(user.getId());
		outboundStatusMapper.insert(outboundStatus);
		return R.ok("审核成功");
	}

	@Override
	public R selectDistributeListByMaterials(OutboundInfoRequest outboundInfoRequest) {
		List<OutbountInfoResponse> outbountInfoResponses=outboundMapper.selectDistributeListByMaterials(outboundInfoRequest);
		if (CollUtil.isNotEmpty(outbountInfoResponses)) {
			OutbountInfoResponse outbountInfoResponse=new OutbountInfoResponse();
			outbountInfoResponse.setMaterials3("合计");
			outbountInfoResponse.setProvince("合计");
			outbountInfoResponse.setQuantity(outbountInfoResponses.stream().map(OutbountInfoResponse::getQuantity).reduce(BigDecimal.ZERO, BigDecimal::add));
			outbountInfoResponse.setTotalPrice(outbountInfoResponses.stream().map(OutbountInfoResponse::getTotalPrice).reduce(BigDecimal.ZERO, BigDecimal::add));
			outbountInfoResponses.add(outbountInfoResponse);
		}
		return R.ok(outbountInfoResponses);
	}

	@Override
	public R selectDistributeListByProvince(OutboundInfoRequest outboundInfoRequest) {
		List<OutbountInfoResponse> outbountInfoResponsescollect=new LinkedList<>();
		List<OutbountInfoResponse> outbountInfoResponses=outboundMapper.selectDistributeListByProvince(outboundInfoRequest);
		List<OutbountInfoResponse> outbountInfoResponses1 = outboundMapper.selectDistributeListByProvincez(outboundInfoRequest);
		if (CollUtil.isNotEmpty(outbountInfoResponses1)) {
			OutbountInfoResponse outbountInfoResponse=new OutbountInfoResponse();
			outbountInfoResponse.setMaterials3("合计");
			outbountInfoResponse.setProvince("合计");
			outbountInfoResponse.setTotalPrice(outbountInfoResponses1.stream().map(OutbountInfoResponse::getTotalPrice).reduce(BigDecimal.ZERO, BigDecimal::add));
			outbountInfoResponsescollect.add(outbountInfoResponse);
		}
		outbountInfoResponses.addAll(outbountInfoResponses1);
		List<OutbountInfoResponse> collect = outbountInfoResponses.stream().sorted(Comparator.comparing(OutbountInfoResponse::getProvince,Comparator.nullsLast(Comparator.naturalOrder()))
				.thenComparing(OutbountInfoResponse::getSort)).collect(Collectors.toList());
		outbountInfoResponsescollect.addAll(collect);
		return R.ok(outbountInfoResponsescollect);
	}

	@Override
	public R selectDistributeListByWarehouse(OutboundInfoRequest outboundInfoRequest) {
		List<OutbountInfoResponse> outbountInfoResponseList=new LinkedList<>();
		List<OutbountInfoResponse> outbountInfoResponses=outboundMapper.selectDistributeListByProvince(outboundInfoRequest);
		List<OutbountInfoResponse> outbountInfoResponses1 = outboundMapper.selectDistributeListByWarehousehz(outboundInfoRequest);
		if (CollUtil.isNotEmpty(outbountInfoResponses1)) {
			OutbountInfoResponse outbountInfoResponse=new OutbountInfoResponse();
			outbountInfoResponse.setMaterials3("合计");
			outbountInfoResponse.setProvince("合计");
			outbountInfoResponse.setWarehouseName("合计");
			outbountInfoResponse.setTotalPrice(outbountInfoResponses1.stream().map(OutbountInfoResponse::getTotalPrice).reduce(BigDecimal.ZERO, BigDecimal::add));
			outbountInfoResponseList.add(outbountInfoResponse);
		}
		outbountInfoResponses.addAll(outbountInfoResponses1);
		List<OutbountInfoResponse> collect = outbountInfoResponses.stream().sorted(Comparator.comparing(OutbountInfoResponse::getWarehouseDeptId)
				.thenComparing(OutbountInfoResponse::getSort)).collect(Collectors.toList());
		outbountInfoResponseList.addAll(collect);
		return R.ok(outbountInfoResponseList);
	}

	@Override
	public R selectDistributeListByOutboundTime(OutboundInfoRequest outboundInfoRequest) {
		List<OutbountInfoResponse> outbountInfoResponses=outboundMapper.selectDistributeListByProvince(outboundInfoRequest);
		List<OutbountInfoResponse> outbountInfoResponses1 = outboundMapper.selectDistributeListByOutboundTimeHz(outboundInfoRequest);
		Map<String, BigDecimal> collect = outbountInfoResponses1.stream().collect(Collectors.toMap(oi -> oi.getOutboundTime() + "and" + oi.getProvince(), OutbountInfoResponse::getTotalPrice));
		outbountInfoResponses.forEach(or->or.setWarehouseTotalPrice(collect.get(or.getOutboundTime() + "and" + or.getProvince())));
		OutbountInfoResponse outbountInfoResponse=new OutbountInfoResponse();
		outbountInfoResponse.setQuantity(outbountInfoResponses.stream().map(OutbountInfoResponse::getQuantity).reduce(BigDecimal.ZERO, BigDecimal::add));
		outbountInfoResponse.setWarehouseTotalPrice(outbountInfoResponses.stream().map(OutbountInfoResponse::getWarehouseTotalPrice).reduce(BigDecimal.ZERO, BigDecimal::add));
		outbountInfoResponses.add(outbountInfoResponse);
		List<OutbountInfoResponse> collect1 = outbountInfoResponses.stream().sorted(Comparator.comparing(OutbountInfoResponse::getOutboundTime, Comparator.nullsLast(Comparator.naturalOrder())).reversed()
				.thenComparing(OutbountInfoResponse::getProvince, Comparator.nullsLast(Comparator.naturalOrder()))
				.thenComparing(OutbountInfoResponse::getWarehouseDeptId, Comparator.nullsLast(Comparator.naturalOrder()))
		).collect(Collectors.toList());
		return R.ok(collect1);
	}

	@Override
	public void exportjzdywztjb(String fileName, String templateFile, List<OutbountInfoResponse> list,HttpServletResponse response) {
		//获取省字典信息
		Map<String, String> province_ch = getProvinceMap("province_ch");
		//拼合计数据到对应的列
		List<OutbountInfoResponse> list1 = new ArrayList<>();
		if(list  != null && !list.isEmpty()){
			for (int i = 0; i < list.size(); i++) {
				OutbountInfoResponse inboundInfoResponse = list.get(i);
				if("合计".equals(inboundInfoResponse.getMaterials3()) || StringUtils.isEmpty(inboundInfoResponse.getMaterials3())){
					list1.add(inboundInfoResponse);
					list.remove(i);
					i--;
				}else{
					inboundInfoResponse.setIndex(i+1);
					// 在字典中拿到省信息
					inboundInfoResponse.setProvinceLabel(province_ch.get(inboundInfoResponse.getProvince()));
				}
			}
		}

//		根据模板生成文件
		List<Integer> strnumToNumColumnIndex = Arrays.asList(4);
		MyFileUtil.listToExcel(response,fileName, templateFile, 0,strnumToNumColumnIndex, list, list1);

	}

	@Override
	public void exportjzdysftjb(String fileName, String templateFile, List<OutbountInfoResponse> list0,HttpServletResponse response) {
		// 获取省字典信息
		Map<String, String> province_ch = getProvinceMap("province_ch");
		//拼合计数据到对应的列
		List<OutbountInfoResponse> list1 = new ArrayList<>();
		if(list0  != null && !list0.isEmpty()){
			for (int i = 0; i < list0.size(); i++) {
				OutbountInfoResponse inboundInfoResponse = list0.get(i);
				if("合计".equals(inboundInfoResponse.getMaterials3()) || StringUtils.isEmpty(inboundInfoResponse.getMaterials3())){
					list1.add(inboundInfoResponse);
					list0.remove(i);
					i--;
				}else{
					inboundInfoResponse.setIndex(i+1);
					// 在字典中拿到省信息
					inboundInfoResponse.setProvinceLabel(province_ch.get(inboundInfoResponse.getProvince()));
				}
			}
		}

//		根据模板生成文件
		MyFileUtil.listToExcel(response,fileName, templateFile, 2,null, list0, list1);

	}

	@Override
	public void exportjzdccktjb(String fileName, String templateFile, List<OutbountInfoResponse> list0,HttpServletResponse response) {
		// 获取省字典信息
		Map<String, String> province_ch = getProvinceMap("province_ch");
		//拼合计数据到对应的列
		List<OutbountInfoResponse> list1 = new ArrayList<>();
		if(list0  != null && !list0.isEmpty()){
			for (int i = 0; i < list0.size(); i++) {
				OutbountInfoResponse inboundInfoResponse = list0.get(i);
				if("合计".equals(inboundInfoResponse.getMaterials3()) || StringUtils.isEmpty(inboundInfoResponse.getMaterials3())){
					list1.add(inboundInfoResponse);
					list0.remove(i);
					i--;
				}else{
					inboundInfoResponse.setIndex(i+1);
					// 在字典中拿到省信息
					inboundInfoResponse.setProvinceLabel(province_ch.get(inboundInfoResponse.getProvince()));
					inboundInfoResponse.setOutProvinceLabel(province_ch.get(inboundInfoResponse.getOutProvince()));
				}
			}
		}
		List<Integer> strnumToNumColumnIndex = Arrays.asList(5);
//		根据模板生成文件
		MyFileUtil.listToExcel(response,fileName, templateFile, 2,strnumToNumColumnIndex, list0, list1);
	}

	@Override
	public void exportjzdypctjb(String fileName, String templateFile, List<OutbountInfoResponse> list0,HttpServletResponse response) {
		// 获取省字典
		Map<String, String> province_ch = getProvinceMap("province_ch");
		//拼合计数据到对应的列
		List<OutbountInfoResponse> list1 = new ArrayList<>();
		if(list0  != null && !list0.isEmpty()){
			for (int i = 0; i < list0.size(); i++) {
				OutbountInfoResponse inboundInfoResponse = list0.get(i);
				if("合计".equals(inboundInfoResponse.getMaterials3()) || StringUtils.isEmpty(inboundInfoResponse.getMaterials3())){
					list1.add(inboundInfoResponse);
					list0.remove(i);
					i--;
				}else{
					inboundInfoResponse.setIndex(i+1);
					// 在字典中拿到省信息
					inboundInfoResponse.setProvinceLabel(province_ch.get(inboundInfoResponse.getProvince()));
				}
			}
		}

//		根据模板生成文件
		List<Integer> strnumToNumColumnIndex = Arrays.asList(8);
		MyFileUtil.listToExcel(response,fileName, templateFile, 4,strnumToNumColumnIndex, list0, list1);
	}

	/**
	 * 	在缓存中获取字典表信息
	 * 	province_ch	省份
	 *	outdound_type	出库类型
	 *	indound_type	入库类型
	 *  ｜详见sys_dict表
	 * @return
	 */
	private Map<String, String> getProvinceMap(String dict_type) {
		Map<String, Map<String, String>> sysDictItemList = sysDictItemService.selectDictItem()
				.stream().collect(Collectors.groupingBy(SysDictItem::getDictType,
						Collectors.toMap(SysDictItem::getItemValue, SysDictItem::getLabel, (p1, p2) -> p2)));
        return sysDictItemList.get(dict_type);
	}

	@Override
	public void exportcjxxxf(String fileName, String templateFile, List<OutboundInfo> outList, HttpServletResponse response) {
		// 查询详情列表
		List<Integer> ids = outList.stream().map(OutboundInfo::getOutboundId).collect(Collectors.toList());
		List<OutboundMaterialInfo> outboundMaterialInfos = outboundMaterialMapper.selectList(Wrappers.<OutboundMaterialInfo>query().lambda().in(OutboundMaterialInfo::getOutboundId, ids));
		// 主表没有规格，需要在详情表找到规格名称（表里存的ID）
		List<SysTreeDict> orderDictList = sysTreeDictMapper.getOrderDictList(1);
		Map<String, String> collect = new HashMap<>();
		Map<String, String> codeAndName = new HashMap<>();
		for (SysTreeDict sysTreeDict : orderDictList) {
			collect.put(sysTreeDict.getId(), sysTreeDict.getName());
			codeAndName.put(sysTreeDict.getName(), sysTreeDict.getCode());
		}
		// 查询字典，找出库类型
//		List<SysDictItem> dictItems = sysDictItemService.selectDictItemByDictType("material_type");

		for (OutboundMaterialInfo outboundMaterialInfo:outboundMaterialInfos){
			outboundMaterialInfo.setMaterialGroup(collect.get(outboundMaterialInfo.getMaterialGroup()));
			outboundMaterialInfo.setMaterialType(collect.get(outboundMaterialInfo.getMaterialType()));
			outboundMaterialInfo.setMaterialName(collect.get(outboundMaterialInfo.getMaterialName()));
			outboundMaterialInfo.setUnit(collect.get(outboundMaterialInfo.getUnit()));
			outboundMaterialInfo.setMaterialCode(codeAndName.get(outboundMaterialInfo.getMaterialName()));
		}

		List<OutboundExcel> list0 = new ArrayList<>();
		List<OutboundExcel> list1 = new ArrayList<>();
		// 获取省字典
		Map<String, String> province_ch = getProvinceMap("province_ch");
		Map<String, String> outdound_type = getProvinceMap("outdound_type");
		//拼合计数据到对应的列
		if(!outList.isEmpty()){
			OutboundExcel totalExcel =new OutboundExcel();
			totalExcel.setInboundTime("合计");
			totalExcel.setQuantity2(BigDecimal.ZERO);
			totalExcel.setTotalPrice2(BigDecimal.ZERO);
			list1.add(totalExcel);
			for (int i = 0; i < outList.size(); i++) {
				for (OutboundMaterialInfo outboundMaterialInfo : outboundMaterialInfos){
					if(outboundMaterialInfo.getOutboundId().equals(outList.get(i).getOutboundId())){
						OutboundExcel outboundExcel = BeanUtil.copyProperties(outList.get(i), OutboundExcel.class);
                        outboundExcel.setIndex(i+1);
						// 主表只有一个物资信息，需要用字表的覆盖
						outboundExcel.setMaterialGroup(outboundMaterialInfo.getMaterialGroup());
						outboundExcel.setMaterialType(outboundMaterialInfo.getMaterialType());
						outboundExcel.setMaterialName(outboundMaterialInfo.getMaterialName());
						outboundExcel.setUnit(outboundMaterialInfo.getUnit());
						outboundExcel.setQuantity2(new BigDecimal(outboundMaterialInfo.getQuantity() == null ? "0" : outboundMaterialInfo.getQuantity()));
						// 计算总数量，有特殊计算逻辑！
						BigDecimal getQuantity = getQuantity(outboundMaterialInfo);
						totalExcel.setQuantity2(totalExcel.getQuantity2().add(getQuantity));
						outboundExcel.setSpecs(outboundMaterialInfo.getSpecs());
						outboundExcel.setInboundTime(outboundMaterialInfo.getInboundTime());
						outboundExcel.setTotalPrice2(new BigDecimal(outboundMaterialInfo.getTotalPrice() == null ? "0" : outboundMaterialInfo.getTotalPrice()));
						totalExcel.setTotalPrice2(totalExcel.getTotalPrice2().add(outboundExcel.getTotalPrice2()));
						outboundExcel.setRemarks(outboundMaterialInfo.getRemarks());
						outboundExcel.setUnitPrice(outboundMaterialInfo.getUnitPrice());
                        // 在字典中拿到省信息
                        outboundExcel.setCalledProvinceName(province_ch.get(outList.get(i).getCalledProvince()));
						outboundExcel.setOutboundType(outdound_type.get(outList.get(i).getOutboundType()));
                        list0.add(outboundExcel);
					}
				}
			}

		}
//		根据模板生成文件
		List<Integer> strnumToNumColumnIndex = Arrays.asList(8,12,13);
		MyFileUtil.listToExcel(response,fileName, templateFile, 2,strnumToNumColumnIndex, list0, list1);
	}

	private BigDecimal getQuantity(OutboundMaterialInfo bean) {
		BigDecimal quantity = new BigDecimal(bean.getQuantity() == null ? "0" : bean.getQuantity());
		switch (bean.getMaterialCode()) {
			case "10305":
				quantity = quantity.multiply(BigDecimal.valueOf(10000L)).divide(BigDecimal.valueOf(500L), 6, BigDecimal.ROUND_HALF_UP);
				break;

			case "10303":
			case "10306":
				quantity = quantity.multiply(BigDecimal.valueOf(10000L)).divide(BigDecimal.valueOf(600L), 6, BigDecimal.ROUND_HALF_UP);
				break;

			case "10310":
				quantity = quantity.multiply(BigDecimal.valueOf(10000L)).divide(BigDecimal.valueOf(300L), 6, BigDecimal.ROUND_HALF_UP);
				break;

			case "10307":
				quantity = quantity.divide(BigDecimal.valueOf(5L), 6, BigDecimal.ROUND_HALF_UP);
				break;

			case "20121":
			case "20120":
				quantity = quantity.multiply(BigDecimal.valueOf(10000L)).divide(BigDecimal.valueOf(20L), 6, BigDecimal.ROUND_HALF_UP);
				break;
		}
		return quantity;
	}
}
