package cn.service.atv.impl;

import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import cn.common.enums.ResultCode;
import cn.common.page.response.Result;
import cn.orm.abs.ISqlToyDao;
import cn.orm.sqltoy.plus.Wrappers;
import cn.orm.sqltoy.plus.query.LambdaQueryWrapper;
import cn.orm.sqltoy.plus.query.QueryWrapper;
import cn.pojo.atv.AtvInventory;
import cn.pojo.atv.AtvOutputAndInputStock;
import cn.pojo.atv.AtvOutputAndInputStockItem;
import cn.pojo.atv.AtvProduct;
import cn.pojo.atv.vo.AtvInputVo;
import cn.service.atv.IAtvOutputAndInputStockService;
import cn.util.core.IsKit;
import cn.util.time.TimeKit;
import cn.util.uuid.UUIDKit;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import javax.annotation.Resource;

/**
 * @Description: 出入库单表
 */
@Service
public class AtvOutputAndInputStockServiceImpl implements IAtvOutputAndInputStockService
{
	@Resource
	private ISqlToyDao daoService;

	/**物品入库*/
	@Override
	public Boolean stockInput(AtvOutputAndInputStock atvOutputAndInputStock, List<AtvOutputAndInputStockItem> atvOutputAndInputStockItems) 
	{
		/** 入库单规则:yymmdd+四位递增的数量 */
		//查询当天最后一张入库单
		LambdaQueryWrapper<AtvOutputAndInputStock> wrapper = Wrappers.lambdaWrapper(AtvOutputAndInputStock.class)
				//.select(AtvOutputAndInputStock::getSn)
				.eq(AtvOutputAndInputStock::getOutIn, 1)
				//CreateTime: yyyy-MM-dd HH:mm:ss;  getToday():yyyy-MM-dd
				.like(AtvOutputAndInputStock::getCreateTime, TimeKit.getToday())
				.orderByDesc(AtvOutputAndInputStock::getCreateTime);
		
		AtvOutputAndInputStock entity = daoService.findOne(wrapper);
		if(IsKit.isNullOrEmpty(entity)) {
			//当天没有入库单（生成第一张）
			atvOutputAndInputStock.setSn("R0"+getDate()+"0001");
		}
		else {
			String sn = entity.getSn();
			atvOutputAndInputStock.setSn("R0"+getDate()+String.format("%0" + sn.substring(8).length() + "d", Integer.parseInt(sn.substring(8)) + 1));
		}
		//写入出入库单表(atv_output_and_input_stock)
		daoService.save(atvOutputAndInputStock);

		int itemNum = atvOutputAndInputStockItems.size();
		int writeItem = 0;
		/**入库单单项(入库单明细)：atv_output_and_input_stock_item*/
		for (AtvOutputAndInputStockItem aoit : atvOutputAndInputStockItems) 
		{
			//后端自动产生的数据
			aoit.setOutputAndInputStockId(atvOutputAndInputStock.getId());
			//页面来的数据
			aoit.setUserId(atvOutputAndInputStock.getUserId());
			aoit.setOutIn(atvOutputAndInputStock.getOutIn());
			aoit.setWarehouseId(atvOutputAndInputStock.getWarehouseId());

			//依据货品ID，获取货品有关信息(从atv_product):属于冗余字段
			QueryWrapper<AtvProduct> wrapperP = Wrappers.wrapper(AtvProduct.class)
					.eq("id", aoit.getProductId());
			AtvProduct entityP = daoService.findOne(wrapperP);
			if(IsKit.isNotNullOrEmpty(entityP)) {
				aoit.setProductTypeId(entityP.getProductTypeId());
				aoit.setSupplierId(entityP.getSupplierId());
				aoit.setProductSn(entityP.getSn());
				aoit.setSpecifications(entityP.getSpecifications());
				aoit.setUnit(entityP.getUnit());
			}
			
			//期初数量 需要查询一下库存表里面关于这个仓库的这个商品的库存有多少 作为期初数量
			//依据品目和仓库ID，从atv_inventory中获取库存信息
			QueryWrapper<AtvInventory> wrapperV = Wrappers.wrapper(AtvInventory.class)
					.eq("warehouseId", atvOutputAndInputStock.getWarehouseId())
					.eq("productId", aoit.getProductId());
			AtvInventory entityV = daoService.findOne(wrapperV);
						
			//不为空代表atv_inventory有此商品的库存，做更新操作
			if(IsKit.isNotNullOrEmpty(entityV)) {
				//给入库单项一个期初数量
				aoit.setInitialQuantity(entityV.getQuantity());
				//给入库单项一个结余数量 就是入库了之后现在的库存数量
				aoit.setFinishQuantity(entityV.getQuantity() + aoit.getQuantity());

				//修改AtvInventory的库存数
				entityV.setQuantity(entityV.getQuantity() + aoit.getQuantity());
				//更新库存 对atvInventory表的quantity字段进行更新
				daoService.update(entityV, "quantity");
			}
			//为空代表atv_inventory中此商品不存在 做新增操作。 
			else {
				//给入库单项一个期初数量  因为无库存  所以是0
				aoit.setInitialQuantity(0);
				//给入库单项一个结余数量 就是入库了之后现在的库存数量
				aoit.setFinishQuantity(aoit.getQuantity());

				//生成库存表数据
				AtvInventory atvInventoryN = new AtvInventory();
				atvInventoryN.setId(UUIDKit.encodingUUID());
				atvInventoryN.setWarehouseId(atvOutputAndInputStock.getWarehouseId());
				atvInventoryN.setProductId(aoit.getProductId());
				atvInventoryN.setQuantity(aoit.getQuantity());

				if(IsKit.isNotNullOrEmpty(entityP)) {
					atvInventoryN.setProductTypeId(entityP.getProductTypeId());
					atvInventoryN.setProductName(entityP.getName());
					atvInventoryN.setProductSn(entityP.getSn());
					atvInventoryN.setSpecifications(entityP.getSpecifications());
					atvInventoryN.setUnit(entityP.getUnit());
				}
				daoService.save(atvInventoryN);
			}
			if(daoService.save(aoit) != null){
				++writeItem;
			}
		}
		return (writeItem == itemNum);
	}

	@Override
	public Result<?> stockOutput(AtvInputVo atvInputVo, List<AtvOutputAndInputStockItem> atvOutputAndInputStockItems) 
	{
		//先做校验 判断有无此库存 以及判断库存是否充足
		for (AtvOutputAndInputStockItem aoit : atvOutputAndInputStockItems)
		{
			QueryWrapper<AtvInventory> wrapperV = Wrappers.wrapper(AtvInventory.class)
					.eq("warehouseId", atvInputVo.getWarehouseId())
					.eq("productId", aoit.getProductId());
			AtvInventory entityV = daoService.findOne(wrapperV);
			
			//为空代表在此仓库没有此商品的库存 返回错误。 
			if (IsKit.isNullOrEmpty(entityV)) {
				return Result.warnMsg(ResultCode.DATA_NOEXIST.getMsg());
			} 
			//不为空代表有此商品的库存，做库存数量校验然后做更新操作
			else {
				if (aoit.getQuantity() > entityV.getQuantity()) {
					return Result.warnMsg(ResultCode.DATA_NOEXIST.getMsg());
				}
			}
		}
		AtvOutputAndInputStock atvOutputAndInputStock = new AtvOutputAndInputStock();
		BeanUtils.copyProperties(atvInputVo, atvOutputAndInputStock);

		/** 出库单规则:yymmdd+四位递增的数量*/ 
		//查询当天最后一张出库单
		LambdaQueryWrapper<AtvOutputAndInputStock> wrapper = Wrappers.lambdaWrapper(AtvOutputAndInputStock.class)
				.eq(AtvOutputAndInputStock::getOutIn,2)
				.like(AtvOutputAndInputStock::getCreateTime, TimeKit.getToday())
				.orderByDesc(AtvOutputAndInputStock::getCreateTime);
		AtvOutputAndInputStock entity = daoService.findOne(wrapper);
		if(IsKit.isNullOrEmpty(entity)) {
			//当天没有出库单（生成第一张）
			atvOutputAndInputStock.setSn("C0"+getDate()+"0001");
		}
		else {
			String sn = entity.getSn();
			atvOutputAndInputStock.setSn("C0"+getDate()+String.format("%0" + sn.substring(8).length() + "d", Integer.parseInt(sn.substring(8)) + 1));
		}
		//写出库单表(一张入库单)：atv_output_and_input_stock
		daoService.save(atvOutputAndInputStock);

		int itemNum = atvOutputAndInputStockItems.size();
		int writeItem = 0;
		//出库单单项(出库单明细)
		for (AtvOutputAndInputStockItem aoit : atvOutputAndInputStockItems) 
		{
			aoit.setId(UUIDKit.encodingUUID());
			//依据品目和仓库ID，从atv_inventory中获取库存信息
			QueryWrapper<AtvInventory> wrapperV = Wrappers.wrapper(AtvInventory.class)
					.eq("warehouseId", atvOutputAndInputStock.getWarehouseId())
					.eq("productId", aoit.getProductId());
			AtvInventory entityV = daoService.findOne(wrapperV);

			//给出库单项一个期初数量
			aoit.setInitialQuantity( entityV.getQuantity());
			//给出库单项一个结余数量 就是出库了之后现在的库存数量
			aoit.setFinishQuantity( entityV.getQuantity() - aoit.getQuantity());
			
			//减少库存数据
			entityV.setQuantity( entityV.getQuantity() - aoit.getQuantity());
			//更新库存数据
			daoService.update(entityV, "quantity");
			
			//写出库单明细到表中atv_output_and_input_stock_item
			aoit.setOutputAndInputStockId(atvOutputAndInputStock.getId());
			aoit.setUserId(atvOutputAndInputStock.getUserId());
			aoit.setWarehouseId(atvOutputAndInputStock.getWarehouseId());
			aoit.setOutIn(atvOutputAndInputStock.getOutIn());

			//依据货品ID，获取货品有关信息(从atv_product):属于冗余字段
			QueryWrapper<AtvProduct> wrapperP = Wrappers.wrapper(AtvProduct.class)
					.eq("id", aoit.getProductId());
			AtvProduct entityP = daoService.findOne(wrapperP);			
			if(IsKit.isNotNullOrEmpty(entityP)) {
				aoit.setProductTypeId(entityP.getProductTypeId());
				aoit.setProductSn(entityP.getSn());
				aoit.setSpecifications(entityP.getSpecifications());
				aoit.setUnit(entityP.getUnit());
				aoit.setSupplierId(entityP.getSupplierId());
			}
			if(daoService.save(aoit) != null){
				++writeItem;
			}
		}
		return Result.ok(writeItem == itemNum);
	}

	/**获取 日期字符串 */
	private String getDate(){
		SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyMMdd");
		return  simpleDateFormat.format(new Date());
	}
}
