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

import cn.hutool.core.bean.BeanUtil;
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.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.emergency.avenue.admin.api.entity.SysDept;
import com.emergency.avenue.admin.api.entity.SysDeptRelation;
import com.emergency.avenue.admin.api.entity.SysTreeDict;
import com.emergency.avenue.admin.api.vo.MaterialFailureVO;
import com.emergency.avenue.admin.api.vo.MaterialOutboundVO;
import com.emergency.avenue.admin.service.SysDeptRelationService;
import com.emergency.avenue.admin.service.SysDeptService;
import com.emergency.avenue.admin.service.SysTreeDictService;
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.*;
import com.emergency.avenue.storage.api.request.MaterialMaintenanceRequest;
import com.emergency.avenue.storage.api.response.MaterialMaintenanceResponse;
import com.emergency.avenue.storage.mapper.*;
import com.emergency.avenue.storage.service.MaterialMaintenanceService;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class MaterialMaintenanceServiceImpl extends ServiceImpl<MaterialMaintenanceMapper,  MaterialMaintenance> implements MaterialMaintenanceService {

	 private final  MaterialMaintenanceMapper materialMaintenanceMapper;
	 private final MaterialMaintenanceDetailMapper materialMaintenanceDetailMapper;
	 private final MaterialMaintenanceStatusMapper materialMaintenanceStatusMapper;
	 private final SysTreeDictService sysTreeDictService;
	 private final MaterialViewMapper materialViewMapper;
	 private final SysDeptRelationService relationService;
	 @Autowired
	 private InboundMaterialMapper inboundMaterialMapper;
	 private final SysDeptService sysDeptService;
	@Override
	public MaterialMaintenance getMaterialMaintenanceById(Integer id) {
		MaterialMaintenance materialMaintenance = materialMaintenanceMapper.selectById(id);
		List<MaterialMaintenanceDetail> materialMaintenanceDetails = materialMaintenanceDetailMapper.selectList(new QueryWrapper<MaterialMaintenanceDetail>().lambda().eq(MaterialMaintenanceDetail::getMaintenanceId, id));
		materialMaintenance.setMaterialMaintenanceDetails(materialMaintenanceDetails);
		List<MaterialMaintenanceStatus> materialMaintenanceStatuses = materialMaintenanceStatusMapper.selectList(new QueryWrapper<MaterialMaintenanceStatus>().lambda().eq(MaterialMaintenanceStatus::getMaintenanceId, id));
		List<SysDept> list1 = sysDeptService.list();
		Map<String, String> collect1 = list1.stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getAbbreviationName));
		materialMaintenanceStatuses.forEach(o->o.setWarehouse(collect1.get(o.getDeptId())));
		materialMaintenance.setMaterialMaintenanceStatuses(materialMaintenanceStatuses);
		List<SysTreeDict> list = sysTreeDictService.getList(1);
		Map<String, String> collect = list.stream().collect(Collectors.toMap(SysTreeDict::getId, SysTreeDict::getName));
		materialMaintenance.setMaterialGroupVo(collect.get(materialMaintenance.getMaterialGroup()));
		materialMaintenance.setMaterialTypeVo(collect.get(materialMaintenance.getMaterialType()));
		materialMaintenance.setMaterialNameVo(collect.get(materialMaintenance.getMaterialName()));
		materialMaintenance.setMaterialUnitVo(collect.get(materialMaintenance.getMaterialUnit()));
		materialMaintenance.setWarehouse(collect1.get(materialMaintenance.getDeptId()));
		return materialMaintenance;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public R saveMaterialMaintenance(MaterialMaintenance materialMaintenance) {
		if(materialMaintenance.getMaterialMaintenanceDetails()!=null&&materialMaintenance.getMaterialMaintenanceDetails().size()>0){
			AvenueUser user = SecurityUtils.getUser();
			materialMaintenance.setDeptId(user.getDeptId());
			materialMaintenance.setUserId(user.getId());
			materialMaintenanceMapper.insert(materialMaintenance);
			for (MaterialMaintenanceDetail materialMaintenanceDetail:materialMaintenance.getMaterialMaintenanceDetails()) {
				materialMaintenanceDetail.setMaintenanceId(materialMaintenance.getId().toString());
				materialMaintenanceDetailMapper.insert(materialMaintenanceDetail);
			}
			if (materialMaintenance.getStatus().equals("2")){
				MaterialMaintenanceStatus build = MaterialMaintenanceStatus.builder().deptId(user.getDeptId())
						.maintenanceId(materialMaintenance.getId().toString())
						.userId(user.getId())
						.status(materialMaintenance.getStatus()).build();
				materialMaintenanceStatusMapper.insert(build);
			}
			}else {
			return R.failed("请添加维护信息");
			}
			return R.ok("添加成功");
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public R updateMaterialMaintenance(MaterialMaintenance materialMaintenance) {
		if(materialMaintenance.getMaterialMaintenanceDetails()!=null&&materialMaintenance.getMaterialMaintenanceDetails().size()>0){
			AvenueUser user = SecurityUtils.getUser();
			materialMaintenanceMapper.updateById(materialMaintenance);
			materialMaintenanceDetailMapper.delete(new QueryWrapper<MaterialMaintenanceDetail>()
			.lambda().eq(MaterialMaintenanceDetail::getMaintenanceId,materialMaintenance.getId()));
			for (MaterialMaintenanceDetail materialMaintenanceDetail:materialMaintenance.getMaterialMaintenanceDetails()) {
				materialMaintenanceDetail.setMaintenanceId(materialMaintenance.getId().toString());
				materialMaintenanceDetail.setId(null);
				materialMaintenanceDetailMapper.insert(materialMaintenanceDetail);
			}
			if (materialMaintenance.getStatus().equals("2")){
				MaterialMaintenanceStatus build = MaterialMaintenanceStatus.builder().deptId(user.getDeptId())
						.maintenanceId(materialMaintenance.getId().toString())
						.userId(user.getId())
						.status(materialMaintenance.getStatus()).build();
				materialMaintenanceStatusMapper.insert(build);
			}
		}else {
			return R.failed("请添加维护信息");
		}
		return R.ok("修改成功");
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean removeByIdAndDetail(Long id) {
		materialMaintenanceDetailMapper.delete(new QueryWrapper<MaterialMaintenanceDetail>()
		.lambda().eq(MaterialMaintenanceDetail::getMaintenanceId,id));
		return SqlHelper.retBool(materialMaintenanceMapper.deleteById(id));
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public R saveInboundStatus(MaterialMaintenanceStatus materialMaintenanceStatus) {
		String deptType = SecurityUtils.getUser().getDeptType();
		AvenueUser user = SecurityUtils.getUser();
		if (materialMaintenanceStatus.getAudi().equals("0")) {
			if (deptType.equals("2")) {
				materialMaintenanceStatus.setStatus("3");
			} else if (deptType.equals("1")) {
				materialMaintenanceStatus.setStatus("5");
			}
		} else {
			if (deptType.equals("2")) {
				materialMaintenanceStatus.setStatus("4");
			} else if (deptType.equals("1")) {
				materialMaintenanceStatus.setStatus("6");
			}
		}
		materialMaintenanceStatusMapper.updatebyIdAndisInvalid(materialMaintenanceStatus.getMaintenanceId());
		MaterialMaintenance materialMaintenance = new MaterialMaintenance();
		materialMaintenance.setStatus(materialMaintenanceStatus.getStatus());
		materialMaintenance.setId(Integer.parseInt(materialMaintenanceStatus.getMaintenanceId()));
		materialMaintenanceMapper.updateById(materialMaintenance);
		materialMaintenanceStatus.setAuditingTime(LocalDateTime.now());
		materialMaintenanceStatus.setDeptId(user.getDeptId());
		materialMaintenanceStatus.setUserId(user.getId());
		materialMaintenanceStatusMapper.insert(materialMaintenanceStatus);
		return R.ok("审核成功");
	}

	@Override
	public R getTimeAndUnitPrice(MaterialView materialView) {
		List<String> deptIds = relationService.list(Wrappers.<SysDeptRelation>lambdaQuery().eq(SysDeptRelation::getAncestor, SecurityUtils.getUser().getDeptId()))
				.stream()
				.map(SysDeptRelation::getDescendant).collect(Collectors.toList());
		QueryWrapper<MaterialView> query = Wrappers.query(materialView);
		query.lambda().gt(MaterialView::getQuantity,0);
		query.lambda().in(MaterialView::getDeptId,deptIds);
		query.lambda().groupBy(MaterialView::getInboundTime,MaterialView::getUnitPrice);
		query.lambda().orderByDesc(MaterialView::getInboundTime,MaterialView::getUnitPrice);
		List<MaterialView> materialViews = materialViewMapper.selectList(query);
		return R.ok(materialViews);
	}

	@Override
	public R getStatistics(MaterialMaintenanceRequest materialMaintenanceRequest) {
		List<String> deptIds = relationService.list(Wrappers.<SysDeptRelation>lambdaQuery().eq(SysDeptRelation::getAncestor, SecurityUtils.getUser().getDeptId()))
				.stream()
				.map(SysDeptRelation::getDescendant).collect(Collectors.toList());
		materialMaintenanceRequest.setDeptIds(deptIds);
		if (StringUtils.isNotEmpty(materialMaintenanceRequest.getMaintenanceUnit())){
			List<MaterialMaintenanceDetail> materialMaintenanceDetails = materialMaintenanceDetailMapper.selectList(Wrappers.<MaterialMaintenanceDetail>lambdaQuery().eq(MaterialMaintenanceDetail::getMaintenanceUnit, materialMaintenanceRequest.getMaintenanceUnit()));
			Set<String> collect = materialMaintenanceDetails.stream().map(MaterialMaintenanceDetail::getMaintenanceId).collect(Collectors.toSet());
			materialMaintenanceRequest.setMaintenanceUnits(collect);
		}
		List<MaterialMaintenanceResponse> statistics = materialMaintenanceStatusMapper.getStatistics(materialMaintenanceRequest);
		if(SecurityUtils.getUser().getDeptType().equals("1")||SecurityUtils.getUser().getDeptType().equals("2")){
			List<SysDept> list1 = sysDeptService.list();
			Map<String, SysDept> collect = list1.stream().collect(Collectors.toMap(SysDept::getDeptId, Function.identity()));
			List<SysTreeDict> list = sysTreeDictService.list();
			Map<String, String> collect1 = list.stream().collect(Collectors.toMap(SysTreeDict::getId, SysTreeDict::getName));
			for (MaterialMaintenanceResponse materialMaintenanceResponse: statistics){
				SysDept sysDept = collect.get(materialMaintenanceResponse.getDeptId());
				materialMaintenanceResponse.setWarehouse(sysDept.getAbbreviationName());
				materialMaintenanceResponse.setGameName(collect.get(sysDept.getParentId()).getAbbreviationName());
				materialMaintenanceResponse.setProvince(sysDept.getDeptProvince());
				materialMaintenanceResponse.setMaterialGroupVo(collect1.get(materialMaintenanceResponse.getMaterialGroup()));
				materialMaintenanceResponse.setMaterialTypeVo(collect1.get(materialMaintenanceResponse.getMaterialType()));
				materialMaintenanceResponse.setMaterialNameVo(collect1.get(materialMaintenanceResponse.getMaterialName()));
				materialMaintenanceResponse.setProvince(collect1.get(materialMaintenanceResponse.getProvince()));
			}
			statistics = statistics.stream()
					.sorted(Comparator.comparing(MaterialMaintenanceResponse::getGameName, Comparator.nullsLast(Comparator.naturalOrder()))
							.thenComparing(MaterialMaintenanceResponse::getProvince, Comparator.nullsLast(Comparator.naturalOrder()))
							.thenComparing(MaterialMaintenanceResponse::getDeptId, Comparator.comparingLong(s -> Optional.ofNullable(s).map(Long::parseLong).orElse(0L)))
							.thenComparing(MaterialMaintenanceResponse::getMaterialGroup, Comparator.reverseOrder())
					).collect(Collectors.toList());
		}
		return R.ok(statistics);
	}

	@Override
	public List<MaterialMaintenanceResponse> getStatisticsbyId(Integer id) {
		List<MaterialMaintenanceResponse> statisticsbyIds = materialMaintenanceStatusMapper.getStatisticsbyId(id);
		if(SecurityUtils.getUser().getDeptType().equals("1")||SecurityUtils.getUser().getDeptType().equals("2")){
			List<SysDept> list1 = sysDeptService.list();
			Map<String, SysDept> collect = list1.stream().collect(Collectors.toMap(SysDept::getDeptId, Function.identity()));
			for (MaterialMaintenanceResponse statisticsbyId: statisticsbyIds) {
				SysDept sysDept = collect.get(statisticsbyId.getDeptId());
				statisticsbyId.setWarehouse(sysDept.getAbbreviationName());
				statisticsbyId.setGameName(collect.get(sysDept.getParentId()).getAbbreviationName());
				statisticsbyId.setProvince(sysDept.getDeptProvince());
				List<SysTreeDict> list = sysTreeDictService.list();
				Map<String, String> collect1 = list.stream().collect(Collectors.toMap(SysTreeDict::getId, SysTreeDict::getName));
				statisticsbyId.setMaterialGroupVo(collect1.get(statisticsbyId.getMaterialGroup()));
				statisticsbyId.setMaterialTypeVo(collect1.get(statisticsbyId.getMaterialType()));
				statisticsbyId.setMaterialNameVo(collect1.get(statisticsbyId.getMaterialName()));
				statisticsbyId.setProvince(collect1.get(statisticsbyId.getProvince()));
			}

		}
		return statisticsbyIds;
	}

	@Override
	public List<MaterialFailureVO> getTimeAndUnitPriceForFailure(MaterialFailureVO materialFailureVO) {
		QueryWrapper<InboundMaterialInfo> wrapper = new QueryWrapper();
		if (materialFailureVO.getMaterialGroup()!=null&&!"".equals(materialFailureVO.getMaterialGroup())){
			wrapper.eq("material_group",materialFailureVO.getMaterialGroup());
		}
		if (materialFailureVO.getMaterialType()!=null&&!"".equals(materialFailureVO.getMaterialType())){
			wrapper.eq("material_type",materialFailureVO.getMaterialType());
		}
		if (materialFailureVO.getMaterialName()!=null&&!"".equals(materialFailureVO.getMaterialName())){
			wrapper.eq("material_name", materialFailureVO.getMaterialName());
		}
		if (materialFailureVO.getMaterialUnit()!=null&&!"".equals(materialFailureVO.getMaterialUnit())){
			wrapper.eq("unit",materialFailureVO.getMaterialUnit());
		}
		wrapper.eq("is_available","0");
		wrapper.lambda().groupBy(InboundMaterialInfo::getInboundTime,InboundMaterialInfo::getUnitPrice);
		wrapper.lambda().orderByDesc(InboundMaterialInfo::getInboundTime,InboundMaterialInfo::getUnitPrice);
		List<InboundMaterialInfo> inboundMaterialInfos = inboundMaterialMapper.selectList(wrapper);
		List<MaterialFailureVO>  materialFailureVOS=new ArrayList<>();
		if (!inboundMaterialInfos.isEmpty()){
			inboundMaterialInfos.forEach(s->{
				MaterialFailureVO failureVO = BeanUtil.toBean(s, MaterialFailureVO.class);
				materialFailureVOS.add(failureVO);
			});
		}
		return materialFailureVOS;
	}

	@Override
	public List<MaterialOutboundVO> getTimeAndUnitPriceForOutbound(MaterialOutboundVO materialOutboundOV) {
		//仓库，物资信息，入库时间，单价，是否可用级联查询
		List<MaterialOutboundVO> materialOutboundVOS = inboundMaterialMapper.selectListByWarehouseIdAndMaterial(materialOutboundOV);
		return materialOutboundVOS;
	}
}
