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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
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.SysDeptRelation;
import com.emergency.avenue.admin.api.entity.SysDictItem;
import com.emergency.avenue.admin.api.entity.SysTreeDict;
import com.emergency.avenue.admin.api.vo.PostExcelVO;
import com.emergency.avenue.admin.mapper.SysDeptMapper;
import com.emergency.avenue.admin.mapper.SysDeptRelationMapper;
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.exception.BusinessException;
import com.emergency.avenue.common.core.exception.ErrorCodes;
import com.emergency.avenue.common.core.util.MsgUtils;
import com.emergency.avenue.common.core.util.R;
import com.emergency.avenue.common.excel.vo.ErrorMessage;
import com.emergency.avenue.common.security.service.AvenueUser;
import com.emergency.avenue.common.security.util.SecurityUtils;
import com.emergency.avenue.storage.api.entity.InboundInfo;
import com.emergency.avenue.storage.api.entity.OutboundInfo;
import com.emergency.avenue.storage.api.entity.OutboundMaterialInfo;
import com.emergency.avenue.storage.api.vo.OutbountExcelVO;
import com.emergency.avenue.storage.mapper.InboundMapper;
import com.emergency.avenue.storage.mapper.OutboundMapper;
import com.emergency.avenue.storage.mapper.OutboundMaterialMapper;
import com.emergency.avenue.storage.service.OutboundService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class OutboundServiceImpl extends ServiceImpl<OutboundMapper, OutboundInfo>  implements OutboundService {
	private final OutboundMapper outboundMapper;
	private final OutboundMaterialMapper outboundMaterialMapper;
	private final SysDeptRelationMapper sysDeptRelationMapper;
	private final InboundMapper inboundMapper;
	private final SysDeptMapper deptMapper;
	private final SysTreeDictMapper sysTreeDictMapper;
	private final SysDeptService sysDeptService;
	private final SysDictItemService sysDictItemService;

	@Override
	@Transactional
	public R saveOutbountAndMaterial(OutboundInfo outboundInfo) {
		String deptId = SecurityUtils.getUser().getDeptId();
		String deptName = SecurityUtils.getUser().getAbbreviationName();
		// 物资信息详情-多条
		List<OutboundMaterialInfo> outboundMaterialInfos = outboundInfo.getOutboundMaterialInfos();
		if (outboundMaterialInfos.size()>0) {
			outboundInfo.setSubmitTime(LocalDateTime.now());
			if(StringUtils.isEmpty(outboundInfo.getDeptId())) {
				outboundInfo.setDeptId(deptId);
				outboundInfo.setWarehouse(deptName);
			}
			outboundInfo.setUserId(SecurityUtils.getUser().getId());
			BigDecimal bigDecimal=new BigDecimal("0");
			BigDecimal bigDecimalzj=new BigDecimal("0.000");
			for (OutboundMaterialInfo outboundMaterialInfo:outboundMaterialInfos){
				bigDecimal=bigDecimal.add(new BigDecimal(outboundMaterialInfo.getQuantity()));
				bigDecimalzj=bigDecimalzj.add(new BigDecimal(outboundMaterialInfo.getTotalPrice()));
			}
			outboundInfo.setQuantity(bigDecimal.toString());
			outboundInfo.setTotalPrice(bigDecimalzj.toString());
			// 出库信息插入
			outboundMapper.insert(outboundInfo);
			for (OutboundMaterialInfo outboundMaterialInfo:outboundMaterialInfos){
				// 校验  部门id、物资名称、入库日期、单价、是否可用
				int i = inboundMapper.inboundCount(outboundInfo.getDeptId(), outboundMaterialInfo);
				if (i<1){
					throw new BusinessException("未找到对应入库信息");
				}
				outboundMaterialInfo.setOutboundId(outboundInfo.getOutboundId());
				// 物资信息表插入
				 outboundMaterialMapper.insert(outboundMaterialInfo);
			}
		}
		return R.ok("新增成功");
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public R updateOutbountAndMaterial(OutboundInfo outboundInfo) {
		String deptId = SecurityUtils.getUser().getDeptId();
		if (outboundInfo.getOutboundId()!=null){
			List<OutboundMaterialInfo> outboundMaterialInfos = outboundInfo.getOutboundMaterialInfos();
			BigDecimal bigDecimal=new BigDecimal("0");
			BigDecimal bigDecimalzj=new BigDecimal("0.000");
			for (OutboundMaterialInfo outboundMaterialInfo:outboundMaterialInfos){
				bigDecimal=bigDecimal.add(new BigDecimal(outboundMaterialInfo.getQuantity()));
				bigDecimalzj=bigDecimalzj.add(new BigDecimal(outboundMaterialInfo.getTotalPrice()));
			}
			outboundInfo.setQuantity(bigDecimal.toString());
			outboundInfo.setTotalPrice(bigDecimalzj.toString());
			outboundMapper.updateById(outboundInfo);
			LambdaQueryWrapper<OutboundMaterialInfo> eq = new QueryWrapper<OutboundMaterialInfo>().lambda().eq(OutboundMaterialInfo::getOutboundId, outboundInfo.getOutboundId());
			outboundMaterialMapper.delete(eq);
			for (OutboundMaterialInfo outboundMaterialInfo:outboundMaterialInfos){
				int i = inboundMapper.inboundCount(deptId, outboundMaterialInfo);
				if (i<1){
					throw new BusinessException("未找到对应入库信息");
				}
				outboundMaterialInfo.setOutboundId(outboundInfo.getOutboundId());
				outboundMaterialInfo.setMaterialId(null);
				outboundMaterialMapper.insert(outboundMaterialInfo);
			}
		}
		return R.ok("修改成功");
	}

	@Override
	public R selectOutAndInAudi() {
		Map map=new HashMap<String,Object>();
		AvenueUser user = SecurityUtils.getUser();
		List<String> deptIds = sysDeptRelationMapper.selectList(Wrappers.<SysDeptRelation>lambdaQuery().eq(SysDeptRelation::getAncestor, user.getDeptId()))
				.stream()
				.map(SysDeptRelation::getDescendant).collect(Collectors.toList());
		QueryWrapper<OutboundInfo> outboundInfoQueryWrapper = new QueryWrapper<>();
		outboundInfoQueryWrapper.lambda().in(OutboundInfo::getDeptId,deptIds);
		if (user.getDeptType().equals("2")){
			outboundInfoQueryWrapper.lambda().in(OutboundInfo::getStatus, Arrays.asList("2","6"));
		}else if (user.getDeptType().equals("1")){
			outboundInfoQueryWrapper.lambda().in(OutboundInfo::getStatus, Arrays.asList("3"));
		}
		Long aLong = outboundMapper.selectCount(outboundInfoQueryWrapper);
		QueryWrapper<InboundInfo> inboundInfoQueryWrapper = new QueryWrapper<>();
		inboundInfoQueryWrapper.lambda().in(InboundInfo::getDeptId,deptIds);
		if (user.getDeptType().equals("2")){
			inboundInfoQueryWrapper.lambda().in(InboundInfo::getStatus, Arrays.asList("2","6"));
		}else if (user.getDeptType().equals("1")){
			inboundInfoQueryWrapper.lambda().in(InboundInfo::getStatus, Arrays.asList("3"));
		}
		Long aLong1 = inboundMapper.selectCount(inboundInfoQueryWrapper);
		Long aLong2 = deptMapper.selectCount(Wrappers.<SysDept>lambdaQuery().eq(SysDept::getDeptType, "3").in(SysDept::getDeptId,deptIds));
		map.put("outaudi",aLong);
		map.put("inaudi",aLong1);
		map.put("warecount",aLong2);
		return R.ok(map);
	}

	@Override
	public R importOut(List<OutbountExcelVO> excelVOList, BindingResult bindingResult,String status) {
		// 通用校验获取失败的数据
		List<ErrorMessage> errorMessageList = (List<ErrorMessage>) bindingResult.getTarget();
		if (CollUtil.isNotEmpty(errorMessageList)) {
			return R.failed(errorMessageList);
		}
		Map<String, SysTreeDict> sysTreeDicts = sysTreeDictMapper.getOrderDictList(1)
				.stream().collect(Collectors.toMap(SysTreeDict::getCode, d -> d, (p1, p2) -> p2));
		Map<String, String> deptMap = sysDeptService.list(Wrappers.<SysDept>lambdaQuery().eq(SysDept::getDeptType, 3))
				.stream().collect(Collectors.toMap(SysDept::getAbbreviationName, SysDept::getDeptId));
		Map<String, Map<String, String>> sysDictItemList = sysDictItemService.selectDictItem()
				.stream().collect(Collectors.groupingBy(SysDictItem::getDictType,
						Collectors.toMap(SysDictItem::getLabel, SysDictItem::getItemValue, (p1, p2) -> p2)));
		Map<String, String> province_ch = sysDictItemList.get("province_ch");
		Map<String, String> outdound_type = sysDictItemList.get("outdound_type");
		// 执行数据插入操作 组装 PostDto
		for (OutbountExcelVO excel : excelVOList) {
			SysTreeDict sysTreeDict = sysTreeDictMapper.selectOne(new QueryWrapper<SysTreeDict>().lambda().eq(SysTreeDict::getName, excel.getMaterialName()));
			String[] codePath = sysTreeDict.getPath().split("/");
			OutboundInfo outboundInfo=new OutboundInfo();
			OutboundMaterialInfo outboundMaterialInfo=new OutboundMaterialInfo();
			BeanUtil.copyProperties(excel, outboundInfo);
			BeanUtil.copyProperties(excel, outboundMaterialInfo);
			outboundInfo.setMaterialGroup(sysTreeDicts.get(codePath[1]).getId());
			outboundInfo.setMaterialType(sysTreeDicts.get(codePath[2]).getId());
			outboundInfo.setMaterialName(sysTreeDict.getId());
			outboundInfo.setOutboundType(outdound_type.get(excel.getOutboundType()));
			outboundMaterialInfo.setOutboundType(outdound_type.get(excel.getOutboundType()));
			outboundMaterialInfo.setMaterialGroup(sysTreeDicts.get(codePath[1]).getId());
			outboundMaterialInfo.setMaterialType(sysTreeDicts.get(codePath[2]).getId());
			outboundMaterialInfo.setMaterialName(sysTreeDict.getId());
			outboundMaterialInfo.setUnit(Optional.ofNullable(sysTreeDicts.get(codePath[3] + "01")).orElse(new SysTreeDict()).getId());
			outboundInfo.setSubmitTime(LocalDateTime.now());
			outboundInfo.setStatus(status);
			outboundInfo.setDeptId(deptMap.get(outboundInfo.getWarehouse()));
			outboundInfo.setCalledProvince(province_ch.get(excel.getProvince()));
			outboundInfo.setTotalPrice(new BigDecimal(outboundInfo.getQuantity()).multiply(new BigDecimal(excel.getUnitPrice())).divide(new BigDecimal("10000")).toString());
			outboundMapper.insert(outboundInfo);
			outboundMaterialInfo.setProvince(province_ch.get(excel.getProvince()));
			outboundMaterialInfo.setTotalPrice(outboundInfo.getTotalPrice());
			outboundMaterialInfo.setOutboundId(outboundInfo.getOutboundId());
			outboundMaterialInfo.setMaterialTree(Arrays.asList(outboundMaterialInfo.getMaterialGroup(),
					outboundMaterialInfo.getMaterialType(),
					outboundMaterialInfo.getMaterialName(),outboundMaterialInfo.getUnit()));
			outboundMaterialMapper.insert(outboundMaterialInfo);
		}
		return R.ok();
	}


}
