
package nccloud.hrkq.hrkq.monthottimevo.action;

import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import nc.bs.logging.Logger;
import nc.vo.bd.defdoc.DefdocVO;
import nc.vo.hi.psndoc.PsnJobVO;
import nc.vo.hrkq.monthottime.AggMonthOtTimeVO;
import nc.vo.hrkq.monthottime.MonthOtTimeBVO;
import nc.vo.hrkq.monthottime.MonthOtTimeVO;
import nc.vo.pub.BusinessException;
import nc.vo.pub.CircularlyAccessibleValueObject;
import nc.vo.pub.VOStatus;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFDateTime;
import nc.vo.pub.lang.UFDouble;
import nccloud.framework.core.exception.ExceptionUtils;
import nccloud.framework.service.ServiceLocator;
import nccloud.framework.web.action.itf.ICommonAction;
import nccloud.framework.web.container.IRequest;
import nccloud.framework.web.ui.pattern.billcard.BillCardOperator;
import nccloud.hrkq.hrkq.monthottimevo.hrkq.util.CommonUtil;
import nccloud.itf.hrkq.hrkq.IMonthottimevoMaintain;
import nccloud.pubitf.riart.pflow.CloudPFlowContext;
import nccloud.pubitf.riart.pflow.ICloudScriptPFlowService;
import nccloud.vo.hrkq.hrkq.MonthOtTimeVOConst;
import nccloud.web.hrkq.common.utils.AttendDataUtil;

/**
 * 主子表保存
 * @version  @since v3.5.6-1903
 */
public class MonthOtTimeVOSaveAction implements ICommonAction {

  @Override
  public Object doAction(IRequest paramIRequest) {
    try {
      BillCardOperator billCardOperator = new BillCardOperator();
      // 1、获取AGGVO （request转换主子VO）
      AggMonthOtTimeVO vo = billCardOperator.toBill(paramIRequest);
      this.doBefore(vo);
      // 2、调用单据的保存动作脚本（savebase），得到保存后结果
      AggMonthOtTimeVO rtnObj = this.callActionScript(vo);
      // 3、处理返回结果（包含功能：根据模板转换前端BillCard，参照翻译，显示公式处理）
      Object billcard = billCardOperator.toCard(rtnObj);
      // 4、返回结果到前端
      return billcard;
    }
    catch (BusinessException ex) {
      // 处理异常信息
      Logger.error(ex);
      ExceptionUtils.wrapException(ex);
    }
    return null;
  }

  /**
   * 动作编码
   *
   * @return
   */
  protected String getActionCode() {
    return MonthOtTimeVOConst.CONST_ACTION_SAVEBASE;
  }

  /**
   * 调用动作脚本
   *
   * @param actionCode
   * @param aggVOs
   * @return
   * @throws BusinessException
   */
  private AggMonthOtTimeVO callActionScript(AggMonthOtTimeVO... aggVOs)
      throws BusinessException {

    String actionCode = this.getActionCode();
    String billType = CommonUtil.getBillTypeCode();

    CloudPFlowContext context = new CloudPFlowContext();
    context.setActionName(actionCode);
    context.setBillType(billType);
    context.setBillVos(aggVOs);
    Logger.debug("开始调用动作脚本 ActionName[" + actionCode + "] BillType[" + billType
        + "]...");

    ICloudScriptPFlowService service =
        ServiceLocator.find(ICloudScriptPFlowService.class);

    Object[] result = service.exeScriptPFlow(context);

    Logger.debug("调用动作脚本 ActionName[" + actionCode + "] BillType[" + billType
        + "]结束");

    String wheresql =
        "pk_monthottime" + "='"
            + ((AggMonthOtTimeVO) result[0]).getPrimaryKey() + "'";
    Collection<AggMonthOtTimeVO> bills =
        CommonUtil.getMDQueryService().queryBillOfVOByCond(
            AggMonthOtTimeVO.class, wheresql, true, false);
    Collection<MonthOtTimeBVO> bbills =
    		CommonUtil.getMDQueryService().queryBillOfVOByCond(MonthOtTimeBVO.class, wheresql, true,
                false);
    AggMonthOtTimeVO[] aggvos = bills.toArray(new AggMonthOtTimeVO[0]);
    aggvos[0].setChildrenVO(bbills.toArray(new MonthOtTimeBVO[0]));
    return bills.toArray(new AggMonthOtTimeVO[0])[0];
  }

    /**
    * 判断新增或修改
    *
    * @param vo
    * @throws BusinessException
    */
  private void doBefore(AggMonthOtTimeVO vo) throws BusinessException {
    String parentPk = vo.getPrimaryKey();
    // 根据是否有主键信息判断是新增保存还是修改保存
    if ((parentPk != null) && !"".equals(parentPk)) {
      // 设置单据默认值
      CircularlyAccessibleValueObject[] allchildren = vo.getAllChildrenVO();
      if (allchildren != null) {
        for (CircularlyAccessibleValueObject obj : allchildren) {
          obj.setAttributeValue("pk_monthottime", parentPk);
          if(StringUtils.isNotBlank(obj.getPrimaryKey()) && VOStatus.UNCHANGED == obj.getStatus()) {
        	  obj.setStatus(VOStatus.UPDATED);
          }
        }
      }
    }
    nc.vo.hrkq.monthottime.MonthOtTimeVO parent = vo.getParentVO();
    PsnJobVO psnjobVO = AttendDataUtil.queryPsnJob(null);
    String pk_psndoc = (String) parent.getAttributeValue(MonthOtTimeVO.PK_PSNDOC);
    if(StringUtils.isNotBlank(pk_psndoc)) {
    	psnjobVO = AttendDataUtil.queryPsnJob(pk_psndoc);
    	pk_psndoc = psnjobVO.getPk_psndoc();
    }
    parent.setAttributeValue(MonthOtTimeVO.PK_PSNDOC,psnjobVO.getPk_psndoc());
    parent.setAttributeValue(MonthOtTimeVO.PK_DEPT,psnjobVO.getPk_dept());
    parent.setAttributeValue(MonthOtTimeVO.PK_ORG,psnjobVO.getPk_org());
    parent.setAttributeValue(MonthOtTimeVO.APPLYDATE,new UFDate());
    parent.setAttributeValue(MonthOtTimeVO.BILLTYPE,MonthOtTimeVOConst.CONST_BILLTYPE_COST);
    parent.setAttributeValue(MonthOtTimeVO.APPROVESTATUS, -1);
//    String org =
//        (String) parent.getAttributeValue(MonthOtTimeVOConst.FIELD_PK_ORG);
    String group = CommonUtil.getGroupByOrg(psnjobVO.getPk_org());
    if ((group != null) && !"".equals(group)) {
      parent.setAttributeValue(MonthOtTimeVOConst.FIELD_PK_GROUP, group);
    }
    
    MonthOtTimeBVO[] bvos = (MonthOtTimeBVO[]) vo.getChildrenVO();
    //加班类型,1为按次ottimestype，2为普通otdatetype
    String otapplytype = (String) parent.getAttributeValue(MonthOtTimeVO.OTAPPLYTYPE);
    if(bvos != null && bvos.length > 0) {
    	IMonthottimevoMaintain service = ServiceLocator.find(IMonthottimevoMaintain.class);
    	List<Map<String, UFDate>> listMap = service.queryHoliday(pk_psndoc, psnjobVO.getPk_org());
    	List<String> defdocList = service.queryDefdoc();//查询节假日类型主键
    	String msg = "";
    	String msg2 = "";
    	Map<String,String> typeMap = new HashMap();
    	List<DefdocVO> defVOList = service.queryDefdoc2();
    	if(defVOList != null && defVOList.size() > 0) {
    		for(DefdocVO defvo : defVOList) {
    			typeMap.put(defvo.getPk_defdoc(), defvo.getName());
    		}
    	}
    	for(MonthOtTimeBVO bvo : bvos) {
    		String type = "";
    		StringBuffer note = new StringBuffer("");
    		if("1".equals(otapplytype)) {//按次
    			type = (String) bvo.getAttributeValue(MonthOtTimeBVO.OTTIMESTYPE);
    			note.append("<br>加班日期类型按次:").append(typeMap.get(bvo.getAttributeValue(MonthOtTimeBVO.OTTIMESTYPE))+"");
    			note.append("<br>加班日期:").append(bvo.getAttributeValue(MonthOtTimeBVO.OTDATE) == null ? "" : bvo.getAttributeValue(MonthOtTimeBVO.OTDATE).toString().substring(0, 10) +"");
    			note.append("<br>开始时间:").append(bvo.getAttributeValue(MonthOtTimeBVO.OVERTIMEBEGINTIME) == null ? "" : bvo.getAttributeValue(MonthOtTimeBVO.OVERTIMEBEGINTIME).toString() +"");
    			note.append("<br>结束时间:").append(bvo.getAttributeValue(MonthOtTimeBVO.OVERTIMEENDTIME) == null ? "" : bvo.getAttributeValue(MonthOtTimeBVO.OVERTIMEENDTIME).toString() +"");
    			note.append("<br>加班次数:").append(bvo.getAttributeValue(MonthOtTimeBVO.OTTIMES) == null ? "" :  new UFDouble(bvo.getAttributeValue(MonthOtTimeBVO.OTTIMES).toString(),1)+"");
    			note.append("<br>加班说明:").append(bvo.getAttributeValue(MonthOtTimeBVO.OTDESCRIPTION) == null ? "" : bvo.getAttributeValue(MonthOtTimeBVO.OTDESCRIPTION).toString() +"");
    			if(StringUtils.isBlank(type)) {
    				throw new BusinessException("加班日期类型按次字段不能为空");
    			}
    		}else if("2".equals(otapplytype)) {//普通
    			type = (String) bvo.getAttributeValue(MonthOtTimeBVO.OTDATETYPE);
    			note.append("<br>加班日期类型:").append(typeMap.get(bvo.getAttributeValue(MonthOtTimeBVO.OTDATETYPE))+"");
    			note.append("<br>加班日期:").append(bvo.getAttributeValue(MonthOtTimeBVO.OTDATE) == null ? "" : bvo.getAttributeValue(MonthOtTimeBVO.OTDATE).toString().substring(0, 10) +"");
    			note.append("<br>开始时间:").append(bvo.getAttributeValue(MonthOtTimeBVO.OVERTIMEBEGINTIME) == null ? "" : bvo.getAttributeValue(MonthOtTimeBVO.OVERTIMEBEGINTIME).toString() +"");
    			note.append("<br>结束时间:").append(bvo.getAttributeValue(MonthOtTimeBVO.OVERTIMEENDTIME) == null ? "" : bvo.getAttributeValue(MonthOtTimeBVO.OVERTIMEENDTIME).toString() +"");
    			note.append("<br>加班时长小时:").append(bvo.getAttributeValue(MonthOtTimeBVO.OTHOURS) == null ? "" :  new UFDouble(bvo.getAttributeValue(MonthOtTimeBVO.OTHOURS).toString(),1)+"");
    			note.append("<br>加班费时长:").append(bvo.getAttributeValue(MonthOtTimeBVO.OTCOSTHOURS) == null ? "" :  new UFDouble(bvo.getAttributeValue(MonthOtTimeBVO.OTCOSTHOURS).toString(),1)+"");
    			note.append("<br>调休时长:").append(bvo.getAttributeValue(MonthOtTimeBVO.LEAVEHOURS) == null ? "" :  new UFDouble(bvo.getAttributeValue(MonthOtTimeBVO.LEAVEHOURS).toString(),1)+"");
    			note.append("<br>加班说明:").append(bvo.getAttributeValue(MonthOtTimeBVO.OTDESCRIPTION) == null ? "" : bvo.getAttributeValue(MonthOtTimeBVO.OTDESCRIPTION).toString() +"");
    			if(StringUtils.isBlank(type)) {
    				throw new BusinessException("加班日期类型字段不能为空");
    			}
    		}
    		
    		bvo.setAttributeValue("note", note.toString());
    		
    		if(bvo.getAttributeValue(MonthOtTimeBVO.OTDATE) == null) {
    			continue;
    		}
    		UFDate otdate = (UFDate) bvo.getAttributeValue(MonthOtTimeBVO.OTDATE);//加班日期是否为节假日
    		if(this.checkDate(otdate, listMap)) {
    			if(type.length() > 0 && !defdocList.contains(type)) {
    				msg = "["+otdate.toString().substring(0,10)+"],";
    			}
    		} else {
    			if(type.length() > 0 && defdocList.contains(type)) {
    				msg2 = "["+otdate.toString().substring(0,10)+"],";
    			}
    		}
    	}
    	if(msg.length() > 0 && msg2.length() > 0) {
    		throw new BusinessException("加班日期"+msg+"属于节假日加班,加班日期"+msg2+"不属于节假日加班，请选择正确的加班类型");
    	}else if(msg.length() > 0) {
    		throw new BusinessException("加班日期"+msg+"属于节假日加班，请选择正确的加班类型");
    	}else if(msg2.length() > 0) {
    		throw new BusinessException("加班日期"+msg2+"不属于节假日加班，请选择正确的加班类型");
    	}
    	
    }
    if("1".equals(otapplytype)) {//按次
    	String dateCheckMsg = CommonUtil.checkSelfTimes(bvos);
	    if(dateCheckMsg != null) {
	    	throw new BusinessException("加班时间范围内存在冲突的加班单据，冲突时间："+dateCheckMsg);
	    }
	    List<MonthOtTimeBVO> oldBvos = CommonUtil.getMaintainService().queryBVOByPkPsndoc(pk_psndoc);
	    if(oldBvos != null && oldBvos.size() > 0) {
	    	String dateTwoCheckMsg = CommonUtil.checkTwoListTimes(bvos,oldBvos.toArray(new MonthOtTimeBVO[0]));
	    	if(dateTwoCheckMsg != null) {
	    		throw new BusinessException("加班时间范围内存在冲突的加班单据，冲突时间："+dateTwoCheckMsg);
	    	}
	    }
    }else if("2".equals(otapplytype)) {//普通
	    String dateCheckMsg = CommonUtil.checkSelf(bvos);
	    if(dateCheckMsg != null) {
	    	throw new BusinessException("加班时间范围内存在冲突的加班单据，冲突时间："+dateCheckMsg);
	    }
	    List<MonthOtTimeBVO> oldBvos = CommonUtil.getMaintainService().queryBVOByPkPsndoc(pk_psndoc);
	    if(oldBvos != null && oldBvos.size() > 0) {
	    	String dateTwoCheckMsg = CommonUtil.checkTwoList(bvos,oldBvos.toArray(new MonthOtTimeBVO[0]));
	    	if(dateTwoCheckMsg != null) {
	    		throw new BusinessException("加班时间范围内存在冲突的加班单据，冲突时间："+dateCheckMsg);
	    	}
	    }
    }
//    String dateCheckMsg = CommonUtil.checkSelf(bvos);
//    if(dateCheckMsg != null) {
//    	throw new BusinessException("加班时间范围内存在冲突的加班单据");
//    }
//    
//    List<MonthOtTimeBVO> oldBvos = CommonUtil.getMaintainService().queryBVOByPkPsndoc(pk_psndoc);
//    if(oldBvos != null && oldBvos.size() > 0) {
//	    String dateTwoCheckMsg = CommonUtil.checkTwoList(bvos,oldBvos.toArray(new MonthOtTimeBVO[0]));
//	    if(dateTwoCheckMsg != null) {
//	    	throw new BusinessException("加班时间范围内存在冲突的加班单据");
//	    }
//    }
  }
  
  /**
   * 判断日期是否符合节假日时间
   * @param otdate
   * @param listMap
   * @return
   */
  private Boolean checkDate(UFDate otdate,List<Map<String, UFDate>> listMap) {
	  Boolean check = Boolean.FALSE;
	  if(listMap != null) {
			for(Map<String, UFDate> map : listMap) {
				UFDate begindate = map.get("begintime");
				UFDate enddate = map.get("endtime");
				if(otdate.compareTo(begindate) >= 0 && otdate.compareTo(enddate) <= 0) {
					check = Boolean.TRUE;
					break;
				}
			}
		}
	  
	  return check;
  }
  
}
