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

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import com.dev.swms.server.model.base.BillType;
import com.dev.swms.server.model.base.Warehouse;
import com.dev.swms.server.model.delivery.DeliveryPlan;
import com.dev.swms.server.model.delivery.DeliveryPlanDetail;
import com.dev.swms.server.model.delivery.DeliveryPlanStatus;
import com.dev.swms.server.model.delivery.ExecutePlan;
import com.dev.swms.server.model.delivery.ExecutePlanDetail;
import com.dev.swms.server.model.delivery.ExecutePlantStatus;
import com.dev.swms.server.model.shipping.PickTicket;
import com.dev.swms.server.model.shipping.PickTicketDetail;
import com.dev.swms.server.model.shipping.PickTicketStatus;
import com.dev.swms.server.service.delivery.DeliveryPlanManager;
import com.dev.energy.server.exception.BusinessException;
import com.dev.energy.server.service.pojo.DefaultBaseManager;
import com.dev.energy.server.util.BeanUtils;

/**
 * @author  dev
 * @description 
 */

public class DefaultDeliveryManager extends DefaultBaseManager implements
		DeliveryPlanManager {

	protected String getDeliveryPlanCode(){
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		return getSequenceGenerater().generateSequence("DP" + sdf.format(new Date()), 4);
	}
	
	protected String getExecutePlanCode(){
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		return getSequenceGenerater().generateSequence("EP" + sdf.format(new Date()), 4);
	}
	
	protected String getPickTicketCode(){
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		return getSequenceGenerater().generateSequence("PT" + sdf.format(new Date()), 4);
	}

	public void storeDeliveryPlan(DeliveryPlan deliveryPlan) {
		if(deliveryPlan.isNew()){
			deliveryPlan.setCode(getDeliveryPlanCode());
			deliveryPlan.setStatus(DeliveryPlanStatus.OPEN);
		}
		commonDao.store(deliveryPlan);
	}

	@SuppressWarnings("unchecked")
	public void addDeliveryPlanDetail(Long deliveryPlanId,
			DeliveryPlanDetail detail) {
		DeliveryPlan dp = load(DeliveryPlan.class,deliveryPlanId);
		if(detail.isNew()){
			dp.addDetail(detail);
		}
		else{
			for(DeliveryPlanDetail dpd : dp.getDetails()){
				if(dpd.getLineNo() == detail.getLineNo()){
					BeanUtils.copyEntity(dpd, detail);
					dpd.setQuantity(detail.getExpectedQuantity());
					Warehouse wh = load(Warehouse.class,1L);
					String warehouseCode = wh.getCode();
					
					String hql = "SELECT ugw.warehouse FROM UserGroupWarehouse ugw WHERE ugw.userGroup.code = :groupCode";
					List<Warehouse> whs = commonDao.findByQuery(hql, new String[]{"groupCode"}, new Object[]{detail.getWarehouse()});
					if(!whs.isEmpty()){
						warehouseCode = whs.get(0).getCode();
					}
					dpd.setWarehouseCode(warehouseCode);
				}
			}
		}
		dp.updateDetailQuantity();
		commonDao.store(dp);
	}
	
	public void removeDeliveryPlanDetail(Long deliveryPlanId,List<Long> ids){
		DeliveryPlan dp = load(DeliveryPlan.class,deliveryPlanId);
		for(Long id : ids){
			DeliveryPlanDetail dpd = load(DeliveryPlanDetail.class,id);
			dp.removeDetail(dpd);
		}
		dp.updateDetailQuantity();
		commonDao.store(dp);
	}

	@SuppressWarnings("unchecked")
	public void active(List<Long> ids) {
		for(Long id : ids){
			DeliveryPlan dp = load(DeliveryPlan.class,id);
			
			String hql = "SELECT max(dpd.id) FROM DeliveryPlanDetail dpd WHERE dpd.deliveryPlan.id = :deliveryPlanId GROUP BY dpd.workGroup,dpd.project,dpd.station,dpd.warehouseCode";
			List<Long> details = commonDao.findByQuery(hql, new String[]{"deliveryPlanId"}, new Object[]{id});
			
			int lineNo = 1;
			for(Long detailId : details){
				DeliveryPlanDetail dpd = load(DeliveryPlanDetail.class,detailId);
				hql = "FROM DeliveryPlanDetail dpd WHERE dpd.deliveryPlan.id = :deliveryPlanId " +
						"AND dpd.workGroup = :workGroup AND dpd.station = :station" +
						"  AND dpd.warehouseCode = :warehouseCode AND dpd.project = :project";
				List<DeliveryPlanDetail> dpds = commonDao.findByQuery(hql, new String[]{"deliveryPlanId","workGroup","station","warehouseCode","project"}, 
						new Object[]{id,dpd.getWorkGroup(),dpd.getStation(),dpd.getWarehouseCode(),dpd.getProject()});
				hql = "FROM Warehouse wh WHERE wh.code = :code";
				Warehouse wh = (Warehouse)commonDao.findByQueryUniqueResult(hql, new String[]{"code"},new Object[]{dpd.getWarehouseCode()});
				ExecutePlan executePlan = new ExecutePlan();
				executePlan.setCode(getExecutePlanCode());
				executePlan.setLineNo(lineNo++);
				executePlan.setWarehouse(wh);
				executePlan.setWarehouseWork(dpd.getWarehouse());
				executePlan.setWorkGroup(dpd.getWorkGroup());
				executePlan.setStation(dpd.getStation());
				executePlan.setPlanDate(dp.getPlanDate());
				executePlan.setStatus(ExecutePlantStatus.OPEN);
				dp.addExecutePlan(executePlan);
				
				int j = 1;
				for(DeliveryPlanDetail d : dpds){
					ExecutePlanDetail epd = d.cloneExecutePlanDetail();
					epd.setLineNo(j++);
					executePlan.addDetail(epd);
				}
				executePlan.updateDetailQuantity();
				commonDao.store(executePlan);
			}
			dp.setStatus(DeliveryPlanStatus.CLOSE);
		}
	}
	
	
	public void activeExecutePlan(List<Long> ids){
		for(Long id : ids){
			ExecutePlan ep = load(ExecutePlan.class,id);
			PickTicket pickTicket = new PickTicket();
			pickTicket.setCode(getPickTicketCode());
			pickTicket.setCompany(ep.getDeliveryPlan().getCompany());
			pickTicket.setWarehouse(ep.getWarehouse());
			pickTicket.setStatus(PickTicketStatus.OPEN);
			pickTicket.setOrderDate(ep.getPlanDate());
			
			String hql = "FROM BillType bt WHERE bt.code = 'DPSN' AND bt.company.id = :companyId";
			BillType billType = (BillType)commonDao.findByQueryUniqueResult(hql, new String[]{"companyId"}, new Object[]{pickTicket.getCompany().getId()});
			if(billType == null){
				throw new BusinessException("executePlan.not.find.billType",new String[]{pickTicket.getCompany().getName()});
			}
			pickTicket.setBillType(billType);
			pickTicket.setUserTracking();
			pickTicket.setExecutePlan(ep.getId());
			pickTicket.setRelatedBill2(pickTicket.getCode());
			commonDao.store(pickTicket);
			
			for(ExecutePlanDetail detail : ep.getDetails()){
				PickTicketDetail ptd = new PickTicketDetail();
				ptd.setItem(detail.getItem());
				ptd.setPackageUnit(detail.getPackageUnit());
				ptd.setOrderQuantity(detail.getExpectedQuantity());
				ptd.setOrderQtyOfMasterUnit(detail.getExpectedQuantity()*detail.getPackageUnit().getConvertFigure());
				pickTicket.addPickTicketDetail(ptd);
			}
			commonDao.store(pickTicket);
			ep.setPickTicket(pickTicket.getCode());
			ep.setStatus(ExecutePlantStatus.ACTIVE);
			commonDao.store(ep);
		}
	}
	
	public void storeExecutePlan(ExecutePlan executePlan){
		commonDao.store(executePlan);
	}
	
	public void removeExecutePlanDetail(Long executePlanId,List<Long> ids){
		ExecutePlan ep = load(ExecutePlan.class,executePlanId);
		for(Long id : ids){
			ExecutePlanDetail epd = load(ExecutePlanDetail.class,id);
			ep.removeDetail(epd);
		}
		ep.updateDetailQuantity();
		commonDao.store(ep);
	}
	
	public void addExecutePlanDetail(Long executePlanId,ExecutePlanDetail detail){
		ExecutePlan ep = load(ExecutePlan.class,executePlanId);
		if(detail.isNew()){
			ep.addDetail(detail);
		}
		else{
			for(ExecutePlanDetail epd : ep.getDetails()){
				if(epd.getLineNo() == detail.getLineNo()){
					BeanUtils.copyEntity(epd, detail);
					epd.setQuantity(detail.getExpectedQuantity());
				}
			}
		}
		ep.updateDetailQuantity();
		commonDao.store(ep);
	}
	
}
