package com.dk.mdm.service.ivt;

import com.dk.common.exception.BaseBusinessException;
import com.dk.common.infrastructure.annotaiton.Pagination;
import com.dk.common.infrastructure.constant.Constant;
import com.dk.common.infrastructure.enums.ErrorCodeEnum;
import com.dk.common.model.pojo.PageList;
import com.dk.common.response.ResponseCodeEnum;
import com.dk.common.response.ResponseResultUtil;
import com.dk.common.response.ResponseResultVO;
import com.dk.mdm.infrastructure.convert.ivt.CheckConvert;
import com.dk.mdm.infrastructure.convert.ivt.CheckItemConvert;
import com.dk.mdm.mapper.ivt.CheckItemMapper;
import com.dk.mdm.mapper.ivt.InventoryMapper;
import com.dk.mdm.model.pojo.ivt.*;
import com.dk.mdm.mapper.ivt.CheckMapper;
import com.dk.common.service.BaseService;
import com.dk.common.mapper.BaseMapper;
import com.dk.mdm.model.pojo.sale.OrderItem;
import com.dk.mdm.model.query.ivt.CheckItemQuery;
import com.dk.mdm.model.query.ivt.CheckQuery;
import com.dk.mdm.model.query.ivt.FreezeItemQuery;
import com.dk.mdm.model.query.ivt.InventoryQuery;
import com.dk.mdm.model.response.ivt.*;
import com.dk.mdm.model.vo.ivt.*;
import com.dk.mdm.model.vo.sale.OrderItemVO;
import com.dk.mdm.service.common.CommonService;
import com.dk.mdm.service.ivt.inbound.InboundCheckService;
import com.dk.mdm.service.ivt.outbound.OutboundCheckService;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Transactional
public class CheckService extends BaseService<Check> {

	@Override
	public BaseMapper<Check> getRepository() {
		return checkMapper;
	}

	@Autowired
	private CheckMapper checkMapper;

	@Autowired
	private CheckConvert checkConvert;

	@Autowired
	private CommonService commonService;

	@Autowired
	private CheckItemConvert checkItemConvert;

	@Autowired
	private CheckItemMapper checkItemMapper;

	@Autowired
	private CheckItemService checkItemService;

    @Autowired
    private InventoryMapper inventoryMapper;

	@Autowired
	private InboundCheckService inboundCheckService;

	@Autowired
	private OutboundCheckService outboundCheckService;


	/**
	 * @desc   : 重写主键
	 * @author : 宋扬
	 * @date   : 2023/3/27 10:39
	 */
	@Override
	public String getPrimaryKey() {
		return "check_id";
	}

	/**
	 * @desc   : 条件查询
	 * @author : 宋扬
	 * @date   : 2023/2/29 10:40
	 */
	@Pagination
	public ResponseResultVO<PageList<CheckResponse>> selectByCond(CheckQuery checkQuery) {
		return super.mergeListWithCount(checkQuery, checkMapper.selectByCond(checkQuery),
				checkMapper.countByCond(checkQuery));
	}

	/**
	 * @desc   : 新建盘点单
	 * @author : 宋扬
	 * @date   : 2024/3/27 11:08
	 */
	@Transactional(rollbackFor = {Exception.class})
	public ResponseResultVO<?> insert(CheckVO checkVO) {
		// 转化实体
		Check check = checkConvert.convertToPo(checkVO);
		Map<String, Object> codeMap = commonService.getUniqueNoteCode(Constant.docNameConstant.Check.getName(), true);
		// 获取冻结状态 获取冻结日期（当前日期） 插入冻结表的实体
		check.setMakeTime(LocalDateTime.now()).setStaffId(checkVO.getStaffId()).setCheckId(codeMap.get("outId").toString())
				.setRemarks(checkVO.getRemarks()).setCheckNo(codeMap.get("outNote").toString()).setCheckDate(LocalDate.now())
				.setOrgId(checkVO.getOrgId()).setFlgLock(checkVO.getFlgLock()).setCheckStatus(checkVO.getCheckStatus())
				.setRemarks(checkVO.getRemarks()).setStaffId(checkVO.getStaffId()).setMakeStaff(checkVO.getMakeStaff());
		// 先插入盘点单主表数据
		super.insert(check);
		// 插入盘点明细
		if (checkVO.getItemList() != null && checkVO.getItemList().size() > 0) {
			for (CheckItemVO checkItemVO : checkVO.getItemList()) {
				CheckItem checkItem = checkItemConvert.convertToPo(checkItemVO);
				// 获取盘点主表uuid
				checkItem.setCheckId(check.getCheckId()).setCheckDate(LocalDate.now())
						.setOInvQty(checkItemVO.getInvQty());
				// 插入盘点单明细数据
				checkItemMapper.insert(checkItem);
				checkItemVO.setFromitemId(checkItem.getItemId()).setIntoingQty(checkItem.getBalanceQty()).setOutingQty(checkItem.getBalanceQty().abs())
						.setFromId(checkItem.getCheckId()).setPriceOut(BigDecimal.ZERO);
			}
		}
		// 判断盘点点状态,如果是完成，需要生成出入库数据
		if(checkVO.getCheckStatus().equals(Constant.CheckStatus.CHECK_STATUS_DONE.getName())){
			// 定义入库Map
			Map<String, Object> inboundCheckMap= new HashMap<>();
			// 定义出库Map
			Map<String, Object> outboundCheckMap= new HashMap<>();
			// 获取入库明细实体
			List<CheckItemVO> inCheckItemVOList = checkVO.getItemList().stream().filter(it -> it.getBalanceQty().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());

			// 盘点差额大于零，则为盘盈数据需生成盘盈入库
			if(inCheckItemVOList!=null && inCheckItemVOList.size()>0){
				// 计算总入库量
				BigDecimal intoQtySum = inCheckItemVOList.stream().map(CheckItemVO::getBalanceQty).reduce(BigDecimal.ZERO, BigDecimal::add)
						.setScale(6, BigDecimal.ROUND_HALF_UP);
				// 计算总入库金额
				BigDecimal intoingAmtSum = inCheckItemVOList.stream().map(CheckItemVO::getIntoingAmt).reduce(BigDecimal.ZERO, BigDecimal::add)
						.setScale(6, BigDecimal.ROUND_HALF_UP);
				// 获取入库总表实体
				InboundVO inboundVO = new InboundVO();

				inboundVO.setOrgId(checkVO.getOrgId()).setStaffId(checkVO.getStaffId()==null?checkVO.getMakeStaff():checkVO.getStaffId())
						.setMakeStaff(checkVO.getMakeStaff()).setIntoingQty(intoQtySum).setFromId(check.getCheckId()).setFromNo(check.getCheckNo())
						.setMakeTime(LocalDateTime.now()).setIntoDate(LocalDate.now()).setWhId(checkVO.getWhId()).setFlgAutoHandle(true)
						.setIntoingAmt(intoingAmtSum).setIntoType(Constant.IntoType.PROFIT.getName());
				// 赋值入库接口参数 总表和明细
				inboundCheckMap.put("total",inboundVO);

				inboundCheckMap.put("detail",inCheckItemVOList);
				// 调用入库接口
				inboundCheckService.checkInboundInsert(inboundCheckMap);
			}

			// 获取出库明细实体
			List<CheckItemVO> outCheckItemVOList = checkVO.getItemList().stream().filter(it -> it.getBalanceQty().compareTo(BigDecimal.ZERO) < 0).collect(Collectors.toList());
			// 盘点差额小于零，则为盘亏数据需生成盘亏出库
			if(outCheckItemVOList!=null && outCheckItemVOList.size()>0){
				// 计算总出库量
				BigDecimal outtoQtySum = outCheckItemVOList.stream().map(CheckItemVO::getBalanceQty).reduce(BigDecimal.ZERO, BigDecimal::add)
						.setScale(6, BigDecimal.ROUND_HALF_UP);
				// 获取出库总表实体
				OutboundVO outboundVO = new OutboundVO();
				outboundVO.setOrgId(checkVO.getOrgId()).setStaffId(checkVO.getStaffId()==null?checkVO.getMakeStaff():checkVO.getStaffId())
						.setMakeStaff(checkVO.getMakeStaff()).setOutingQty(outtoQtySum.abs()).setFromId(checkVO.getCheckId())
						.setFromNo(checkVO.getCheckNo()).setMakeTime(LocalDateTime.now()).setOutDate(LocalDate.now())
						.setOutingAmt(BigDecimal.ZERO).setOutType(Constant.OutType.INVENTORY_LOSS.getName());
				// 赋值出库接口参数 总表和明细
				outboundCheckMap.put("total",outboundVO);
				outboundCheckMap.put("detail",outCheckItemVOList);
				// 调用盘点出库接口
				outboundCheckService.otherOutboundInsert(outboundCheckMap);
			}
		}
		return ResponseResultUtil.success();
	}


	/**
	 * @desc   : 通过ID获取编辑盘点单信息
	 * @author : 宋扬
	 * @date   : 2024/3/28 15:38
	 */
	public ResponseResultVO<?> getCheckForUpdate(String id) {
		Map<String, Object> dataInfo = new HashMap<>();
		CheckResponse checkResponse = checkMapper.selectById(id);
		dataInfo.put("data", checkResponse);
		// 商品明细
		List<CheckItemResponse> checkItem = checkItemMapper.selectByCond(new CheckItemQuery().setCheckId(id));
		dataInfo.put("dataItem", checkItem);
		return ResponseResultUtil.success(dataInfo);
	}

	/**
	 * @desc   : 编辑盘点单
	 * @author : 宋扬
	 * @date   : 2024/3/28 16:51
	 */
	@Transactional(
			rollbackFor = {Exception.class}
	)
	public ResponseResultVO<?> update(CheckVO checkVO) {
		// 明细实体（避免并发，需要再查一遍）
		CheckItem checkItemForUpdate;
		// 转化实体
		Check check = checkConvert.convertToPo(checkVO);
		//删除的
		if(checkVO.getDeleteItemList()!=null){
			List<CheckItemVO> deleteCheckItemVOList = checkVO.getDeleteItemList().stream().filter(it -> it.getItemId() != null).collect(Collectors.toList());
			if (deleteCheckItemVOList.size() > 0) {
				for (CheckItemVO checkItemVO : deleteCheckItemVOList) {
					checkItemForUpdate = checkItemMapper.selectByIdForUpdate(checkItemVO.getItemId());
					checkItemMapper.deleteById(checkItemVO.getItemId());
				}
			}
		}
		if(checkVO.getItemList()!=null) {
			//新建
			List<CheckItemVO> insertCheckItemVOList = checkVO.getItemList().stream().filter(it -> it.getItemId() == null).collect(Collectors.toList());
			for (CheckItemVO checkItemVO : insertCheckItemVOList) {
				CheckItem checkItem = checkItemConvert.convertToPo(checkItemVO);
				// 获取盘点主表uuid
				checkItem.setCheckId(check.getCheckId()).setCheckDate(LocalDate.now())
						.setOInvQty(checkItemVO.getInvQty());
				// 插入盘点单明细数据
				checkItemMapper.insert(checkItem);
				checkItemVO.setFromitemId(checkItem.getItemId()).setIntoingQty(checkItem.getBalanceQty())
						.setOutingQty(checkItem.getBalanceQty().abs()).setFromId(checkItem.getCheckId())
						.setPriceOut(BigDecimal.ZERO);
			}
			// 编辑
			List<CheckItemVO> editCheckItemVOList = checkVO.getItemList().stream().filter(it -> it.getItemId() != null).collect(Collectors.toList());
			for (CheckItemVO checkItemVO : editCheckItemVOList) {
				// 查询锁表
				checkItemForUpdate = checkItemMapper.selectByIdForUpdate(checkItemVO.getItemId());
				// 转化实体
				CheckItem checkItem = checkItemConvert.convertToPo(checkItemVO);
				// 获取存货明细里的存货数量
				InventoryResponse inventoryResponse = inventoryMapper.selectById(checkItemVO.getInvId());
				// 赋值库存数量
				checkItem.setInvQty(inventoryResponse.getInvQty());
				// 修改盘点明细
				checkItemService.updateByUuid(checkItem);
			}
		}

		// 赋值盘点状态、ID和备注
		check.setCheckId(checkVO.getCheckId()).setCheckStatus(checkVO.getCheckStatus()).setRemarks(checkVO.getRemarks());
		// 判断盘点点状态,如果是完成，需要生成出入库数据
		if(checkVO.getCheckStatus().equals(Constant.CheckStatus.CHECK_STATUS_DONE.getName())){
			// 定义入库Map
			Map<String, Object> inboundCheckMap= new HashMap<>();
			// 定义出库Map
			Map<String, Object> outboundCheckMap= new HashMap<>();
			// 获取入库明细实体
			List<CheckItemVO> inCheckItemVOList = checkVO.getItemList().stream().filter(it -> it.getBalanceQty().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
			// 盘点差额大于零，则为盘盈数据需生成盘盈入库
			if(inCheckItemVOList!=null && inCheckItemVOList.size()>0){
				// 计算总入库量
				BigDecimal intoQtySum = inCheckItemVOList.stream().map(CheckItemVO::getBalanceQty).reduce(BigDecimal.ZERO, BigDecimal::add)
						.setScale(6, BigDecimal.ROUND_HALF_UP);
				// 计算总入库金额
				BigDecimal intoingAmtSum = inCheckItemVOList.stream().map(CheckItemVO::getIntoingAmt).reduce(BigDecimal.ZERO, BigDecimal::add)
						.setScale(6, BigDecimal.ROUND_HALF_UP);
				// 获取入库总表实体
				InboundVO inboundVO = new InboundVO();
				inboundVO.setOrgId(checkVO.getOrgId()).setStaffId(checkVO.getStaffId()==null?checkVO.getMakeStaff():checkVO.getStaffId())
						.setMakeStaff(checkVO.getMakeStaff()).setIntoingQty(intoQtySum).setFromId(checkVO.getCheckId())
						.setFromNo(checkVO.getCheckNo()).setMakeTime(LocalDateTime.now()).setIntoDate(LocalDate.now()).setWhId(checkVO.getWhId())
						.setFlgAutoHandle(true).setIntoingAmt(intoingAmtSum).setIntoType(Constant.IntoType.PROFIT.getName());
				// 编辑时需要清空item_id值
				for (CheckItemVO checkItemVO : inCheckItemVOList) {
					checkItemVO.setItemId(null);
				}
				// 赋值入库接口参数 总表和明细
				inboundCheckMap.put("total",inboundVO);
				inboundCheckMap.put("detail",inCheckItemVOList);
				// 调用入库接口
				inboundCheckService.checkInboundInsert(inboundCheckMap);
			}

			// 获取出库明细实体
			List<CheckItemVO> outCheckItemVOList = checkVO.getItemList().stream().filter(it -> it.getBalanceQty().compareTo(BigDecimal.ZERO) < 0).collect(Collectors.toList());
			// 盘点差额小于零，则为盘亏数据需生成盘亏出库
			if(inCheckItemVOList!=null && inCheckItemVOList.size()>0){
				// 计算总出库量
				BigDecimal outtoQtySum = outCheckItemVOList.stream().map(CheckItemVO::getBalanceQty).reduce(BigDecimal.ZERO, BigDecimal::add)
						.setScale(6, BigDecimal.ROUND_HALF_UP);
				// 获取出库总表实体
				OutboundVO outboundVO = new OutboundVO();
				outboundVO.setOrgId(checkVO.getOrgId()).setStaffId(checkVO.getStaffId()==null?checkVO.getMakeStaff():checkVO.getStaffId())
						.setMakeStaff(checkVO.getMakeStaff()).setOutingQty(outtoQtySum.abs()).setFromId(checkVO.getCheckId())
						.setFromNo(checkVO.getCheckNo()).setMakeTime(LocalDateTime.now()).setOutDate(LocalDate.now()).setOutingAmt(BigDecimal.ZERO)
						.setOutType(Constant.OutType.INVENTORY_LOSS.getName());

				// 编辑时需要清空item_id值
				for (CheckItemVO checkItemVO : inCheckItemVOList) {
					checkItemVO.setItemId(null);
				}
				// 赋值出库接口参数 总表和明细
				outboundCheckMap.put("total",outboundVO);
				outboundCheckMap.put("detail",inCheckItemVOList);
				// 调用盘点出库接口
				outboundCheckService.otherOutboundInsert(outboundCheckMap);
			}
		}
		// 更新盘点总单
		return ResponseResultUtil.success(super.updateByUuid(check));
	}

}
