package com.dev.swms.server.service.receiving.pojo;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.dev.swms.server.model.base.Item;
import com.dev.swms.server.model.base.ItemKey;
import com.dev.swms.server.model.base.LotInfo;
import com.dev.swms.server.model.base.Structure;
import com.dev.swms.server.model.base.PackageUnit;
import com.dev.swms.server.model.receiving.ReceivedDoc;
import com.dev.swms.server.model.receiving.ReceivingDoc;
import com.dev.swms.server.model.receiving.ReceivingDocDetail;
import com.dev.swms.server.model.receiving.ReceivingDocStatus;
import com.dev.swms.server.model.receiving.ReceivingDocType;
import com.dev.swms.server.model.rules.LotRule;
import com.dev.swms.server.service.base.ItemManager;
import com.dev.swms.server.service.base.WarehouseManager;
import com.dev.swms.server.service.inventory.InventoryManager;
import com.dev.swms.server.service.receiving.PutawayAllocator;
import com.dev.swms.server.service.receiving.ReceivingDocManager;
import com.dev.swms.server.service.sequence.BussinessCodeManager;
import com.dev.swms.server.utils.DoubleUtils;
import com.dev.swms.server.web.filter.WarehouseHolder;
import com.dev.energy.server.exception.BusinessException;
import com.dev.energy.server.service.pojo.DefaultBaseManager;
import com.dev.energy.server.util.LocalizedMessage;

/**
 * @author  dev
 * 
 */
public class DefaultReceivingDocManager extends DefaultBaseManager implements
		ReceivingDocManager {
	protected final ItemManager itemManager;
	protected final InventoryManager inventoryManager;
	protected final BussinessCodeManager bussinessCodeManager;
	protected final PutawayAllocator putawayAllocator;
	protected final WarehouseManager warehouseManager;

	public DefaultReceivingDocManager(ItemManager manager,
			InventoryManager inventoryManager,BussinessCodeManager bussinessCodeManager, 
			PutawayAllocator putawayAllocator, WarehouseManager warehouseManager) {
		super();
		itemManager = manager;
		this.inventoryManager = inventoryManager;
		this.bussinessCodeManager = bussinessCodeManager;
		this.putawayAllocator = putawayAllocator;
		this.warehouseManager = warehouseManager;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.dev.swms.server.service.receive.ReceivingDocManager#addReceivingDocDetail(java.lang.Long,
	 *      com.dev.swms.server.model.receiving.ReceivingDocDetail)
	 */
	 public void addReceivingDocDetail(Long receivingDocId, ReceivingDocDetail receivingDocDetail) {
			ReceivingDoc receivingDoc = commonDao.load(ReceivingDoc.class, receivingDocId);
			PackageUnit packUnit = commonDao.load(PackageUnit.class, receivingDocDetail.getPackageUnit().getId());
			receivingDocDetail.setExpectedQuantity(
					DoubleUtils.formatByPrecision(receivingDocDetail.getExpectedQuantity(), packUnit.getPrecision()));
			receivingDocDetail.setExpectedQtyOfMasterUnit(receivingDocDetail.getExpectedQuantity()*packUnit.getConvertFigure());
			if (receivingDocDetail.getExpectedQuantity() <= 0) {
				throw new BusinessException("docDetail.add.quantityError");
			}
			Item item = this.commonDao.load(Item.class,receivingDocDetail.getItem().getId());
	
			//写入供应商的名称到lotInfo
			if(receivingDocDetail.getLotInfo().getPropL1()!=null && receivingDocDetail.getLotInfo().getPropL1()!=0){
				Structure supplier = this.commonDao.load(Structure.class, receivingDocDetail.getLotInfo().getPropL1());
				receivingDocDetail.getLotInfo().setPropLC1(supplier.getName());
			}
			
			if (ReceivingDocStatus.OPEN.equals(receivingDoc.getStatus())) {
				//新增日期自动计算功能
				if (item.getDefaultLotRule() != null && item.getDefaultLotRule().getLotRuleComponent().getTrackPropD1()) {
					if (receivingDocDetail.getLotInfo().getPropD1() == null 
							&& receivingDocDetail.getLotInfo().getPropD2() != null){
						receivingDocDetail.getLotInfo().setInvaidStart(item);
					} else if (receivingDocDetail.getLotInfo().getPropD1() != null 
							&& receivingDocDetail.getLotInfo().getPropD2() == null) {
						receivingDocDetail.getLotInfo().setInvaidEnd(item);
					}
				}
				
				
				PackageUnit unit = commonDao.load(PackageUnit.class, receivingDocDetail.getPackageUnit().getId());
				Integer lineNo = receivingDocDetail.getLineNo();
				if (!unit.getItem().getId().equals(receivingDocDetail.getItem().getId())) {
					throw new BusinessException("docDetail.itemPackageUnit.disMatch");
				}
				
				//新增明细
				if (receivingDocDetail.isNew()) {
					receivingDoc.addReceivingDocDetail(receivingDocDetail);
				//修改明细
				} else {
					LotInfo lotInfo = receivingDocDetail.getLotInfo();
					
				    double newQuantity = receivingDocDetail.getExpectedQuantity();
				    receivingDocDetail = commonDao.load(ReceivingDocDetail.class, receivingDocDetail.getId());
				    double deltaQuantity = newQuantity - receivingDocDetail.getExpectedQuantity();
				    if ((newQuantity - receivingDocDetail.getAsnQuantity()) < 0) {
				    	throw new BusinessException("receivingDocDetail.expectedQuantity.error");
				    }
				    receivingDocDetail.setItem(item);
					receivingDocDetail.setPackageUnit(unit);
					receivingDocDetail.setLineNo(lineNo);
					receivingDocDetail.setLotInfo(lotInfo);
					receivingDoc.addExpectedQuantity(receivingDocDetail, deltaQuantity);
				    if (receivingDocDetail.getExpectedQuantity() == 0) {
				    	receivingDoc.getReceivingDocDetails().remove(receivingDocDetail);
				    }
				}
				commonDao.store(receivingDoc);
			}
			
		}
	/*
	 * (non-Javadoc)
	 * 
	 * @see com.dev.swms.server.service.receive.ReceivingDocManager#removeReceivingDocDetail(java.lang.Long,
	 *      java.util.List)
	 */
	public void removeReceivingDocDetail(Long receivingDocId,
			List<Long> receivingDocDetailIds) {
		ReceivingDoc receivingDoc = commonDao.load(ReceivingDoc.class,
				receivingDocId);
		receivingDoc.removeDetails(receivingDocDetailIds);
	}
	

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.dev.swms.server.service.receive.ReceivingDocManager#storeReceivingDoc(com.dev.swms.server.model.receiving.ReceivingDoc)
	 */
	public void storeReceivingDoc(ReceivingDoc receivingDoc) {
		//保存收货单
		if (receivingDoc.isNew()) {
			receivingDoc.setWarehouse(WarehouseHolder.getWarehouse());
			receivingDoc.setCode(this.bussinessCodeManager.generateReceivingDocCode(new HashMap()));
			receivingDoc.setStatus(ReceivingDocStatus.OPEN);
			receivingDoc.setType(ReceivingDocType.RECEIVE);
			receivingDoc.setUserTracking();
		}
		this.store(receivingDoc);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.dev.swms.server.service.receive.ReceivingDocManager#deleteAll(java.util.List)
	 */
	public void deleteAll(List<Long> receivingDocIds) {
		String errMsg = "";
		for (Long id : receivingDocIds) {
			ReceivingDoc receivingDoc = commonDao.load(ReceivingDoc.class, id);
			if (ReceivingDocStatus.OPEN.equals(receivingDoc.getStatus())) {
				commonDao.delete(receivingDoc);
				errMsg+=receivingDoc.getCode()+" 单据删除成功;";
			}
			else
				errMsg+=receivingDoc.getCode()+" 单据删除失败;";
		}
		LocalizedMessage.addLocalizedMessage(errMsg);
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see com.dev.swms.server.service.receiving.ReceivingDocManager#closeAll(java.util.List)
	 */
	public void closeAll(List<Long> receivingDocIds) {
		String errMsg = "";
		for (Long id : receivingDocIds) {
			ReceivingDoc receivingDoc = commonDao.load(ReceivingDoc.class, id);
			if (receivingDoc.close()) {
				errMsg+=receivingDoc.getCode()+" 单据关闭成功;";
			}
			else
				errMsg+=receivingDoc.getCode()+" 单据关闭失败;";
		}
		LocalizedMessage.addLocalizedMessage(errMsg);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.dev.swms.server.service.receiving.ReceivingDocManager#cancelAll(java.util.List)
	 */
	public void cancelAll(List<Long> receivingDocIds) {
		String errMsg = "";
		for (Long id : receivingDocIds) {
			ReceivingDoc receivingDoc = commonDao.load(ReceivingDoc.class, id);
			if (receivingDoc.cancel()) {
				errMsg+=receivingDoc.getCode()+" 单据取消成功;";
			}
			else
				errMsg+=receivingDoc.getCode()+" 单据取消失败;";
		}
		LocalizedMessage.addLocalizedMessage(errMsg);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.dev.swms.server.service.receiving.ReceivingDocManager#getLeftQuantityByDetail(java.lang.Long)
	 */
	public String getExpectedQuantityByDetail(Map map) {
		Long receivingDocDetailId = (Long) map.get("receivingDocDetail.id");
		if (receivingDocDetailId == null) {
			return "0";
		}
		ReceivingDocDetail detail = commonDao.load(ReceivingDocDetail.class,
				receivingDocDetailId);
		
		return String.valueOf(getAvaliableQuantityByDetail(detail))+detail.getPackageUnit().getUnit();
	}

	private Double getAvaliableQuantityByDetail(ReceivingDocDetail detail) {
		Double asnQuantity = (Double) commonDao.findByNamedQueryUniqueResult("getAsnReceivedQuantityByReceivingDocDetailId", new String[] {"receivingDocDetailId"}, new Object[] {detail.getId()});
		PackageUnit orderPack = this.commonDao.load(PackageUnit.class, detail.getPackageUnit().getId());
		if(asnQuantity==null){
			return Math.floor((detail.getExpectedQtyOfMasterUnit()-detail.getReceivedQuantity()-detail.getAsnQuantity())/orderPack.getConvertFigure());
		}
		return Math.floor((detail.getExpectedQtyOfMasterUnit()-(detail.getReceivedQuantity()-asnQuantity)-detail.getAsnQuantity())/orderPack.getConvertFigure());
	 
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see com.dev.swms.server.service.receiving.ReceivingDocManager#activeAll(java.util.List)
	 */
	public void activeAll(List<Long> receivingDocIds) {
		int i = 0;
		for (Long id : receivingDocIds) {
			ReceivingDoc receivingDoc = commonDao.load(ReceivingDoc.class, id);
			if (receivingDoc.active()) {
				commonDao.store(receivingDoc);
				i++;
			}

		}
		LocalizedMessage.addMessage("receivingDoc.active.success",
				new String[] { String.valueOf(i) });
	}

	/*
	 * (non-Javadoc)
	 * @see com.dev.swms.server.service.receiving.ReceivingDocManager#inactiveAll(java.util.List)
	 */
	public void inactiveAll(List<Long> receivingDocIds) {
		int i = 0;
		for (Long id : receivingDocIds) {
			ReceivingDoc receivingDoc = commonDao.load(ReceivingDoc.class, id);
			if (receivingDoc.inactive()) {
				commonDao.store(receivingDoc);
				i++;
			}
		}
		LocalizedMessage.addMessage("receivingDoc.inactive.success",
				new String[] { String.valueOf(i) });
	}

	public ReceivingDoc getReceivingDocByCode(String code) {
		List result = commonDao.findByNamedQuery("getReceivingDocByCode",
				new String[] { "code" }, new String[] { code });
		if (result.size() >= 1) {
			return (ReceivingDoc) result.get(0);
		}
		return null;
	}

	public ReceivingDocDetail getReceivingDocDetailByItem(Long docId, String itemCode, int type) {
		ReceivingDoc receivingDoc = commonDao.load(ReceivingDoc.class,docId);
		for(ReceivingDocDetail detail : receivingDoc.getReceivingDocDetails()){
			if (detail.getItem().getCode().equals(itemCode)){
				if (type == 0) {
					return detail;
				} else if (detail.getExpectedQtyOfMasterUnit()-detail.getReceivedQuantity()>0) {
					return detail;
				}
			}
		}
		return null;
	}

	public PackageUnit getUnit(Long detailId) {
		ReceivingDocDetail detail = commonDao.load(ReceivingDocDetail.class,detailId);
		PackageUnit unit = commonDao.load(PackageUnit.class, detail.getPackageUnit().getId());
		return unit;
	}

	public ReceivingDocDetail getReceivingDocDetailByItemKey(ItemKey itemKey) {
		Long itemKeyId=itemKey.getId();
		List result=commonDao.findByNamedQuery("getReceivingDocDetailByItemKey",new String[]{"itemKeyId"},new Object[]{itemKeyId});
		if(result.size()==1){
			return (ReceivingDocDetail)result.get(0);
		}
		return null;
	}

	public ReceivedDoc getReceivedDocByCode(String code, String receivedCode, int type) {
		List result = null;
		if (type == 1) {
			result = commonDao.findByNamedQuery("getReceivedDocByREVCode",
					new String[] { "REVCode", "receivedCode" }, new String[] { code, receivedCode });
		} else {
			result = commonDao.findByNamedQuery("getReceivedDocByASNCode",
					new String[] { "ASNCode", "receivedCode" }, new String[] { code, receivedCode });
		}
		if (result.size() >= 1) {
			return (ReceivedDoc) result.get(0);
		}
		return null;
	}

}
