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 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.pf.change.PfUtilBaseTools;
import nc.vo.pub.BusinessException;
import nc.vo.pub.CircularlyAccessibleValueObject;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFDateTime;
import nc.vo.pub.lang.UFDouble;
import nc.vo.uap.pf.PfProcessBatchRetObject;
import nccloud.framework.core.exception.ExceptionUtils;
import nccloud.framework.core.json.IJson;
import nccloud.framework.service.ServiceLocator;
import nccloud.framework.web.action.itf.ICommonAction;
import nccloud.framework.web.container.IRequest;
import nccloud.framework.web.container.SessionContext;
import nccloud.framework.web.json.JsonFactory;
import nccloud.framework.web.ui.pattern.billcard.BillCardOperator;
import nccloud.hrkq.hrkq.monthottimevo.hrkq.util.CommonUtil;
import nccloud.hrkq.hrkq.monthottimevo.hrkq.util.NccBillOperatorParam;
import nccloud.hrkq.hrkq.monthottimevo.hrkq.util.NccCommitReturnInfo;
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.hr.pub.HRNccTemplateUtils;
import nccloud.web.hrkq.common.utils.AttendDataUtil;
import nccloud.web.uapbd.commons.web.ParamUtils;
import nccloud.web.workflow.approve.util.NCCFlowUtils;

public class MonthOtTimeVOCommonSaveAction implements ICommonAction {

	@Override
	public Object doAction(IRequest request) {
		ParamUtils param = new ParamUtils(request);
		Object obj = param.get("formData");
		IJson json = JsonFactory.create();
		MonthOtTimeBVO[] bvos = HRNccTemplateUtils.getVOFromGrid(MonthOtTimeBVO.class, json.toJson(obj));
		String appCode = param.getString("appCode",SessionContext.getInstance().getAppcode());
		String userid = SessionContext.getInstance().getClientInfo().getUserid();
		PsnJobVO psnJob = AttendDataUtil.queryPsnJob(null);
		MonthOtTimeVO vo = new MonthOtTimeVO();
		try {
			BillCardOperator billCardOperator = new BillCardOperator();
			setValue(vo,psnJob,appCode);
			vo.setAttributeValue(MonthOtTimeVO.WITNESS, bvos[0].getAttributeValue(MonthOtTimeBVO.VBDEF8));
			AggMonthOtTimeVO aggVO = new AggMonthOtTimeVO();
			aggVO.setParentVO(vo);
			for(MonthOtTimeBVO bvo : bvos) {
				if(bvo.getAttributeValue("otdate") != null) {
					bvo.setAttributeValue("otdate",new UFDateTime(bvo.getAttributeValue("otdate").toString()).getDate());
				}
				if(bvo.getAttributeValue("overtimebegintime") != null) {
					bvo.setAttributeValue("otdate",new UFDateTime(bvo.getAttributeValue("overtimebegintime").toString()).getDate());
				}
			}
			
			aggVO.setChildrenVO(bvos);
			//添加校验功能
			doBefore(aggVO);
			
			// 2、调用单据的保存动作脚本（savebase），得到保存后结果
		    AggMonthOtTimeVO rtnObj = this.callActionScript(aggVO);
		    // 获取前端请求参数
		    NccBillOperatorParam operaParam = this.getRequestParam(request);
		    Object resultVOs = this.commit(new AggMonthOtTimeVO[] {rtnObj}, operaParam.getUserObj());
		    // 3、处理返回结果（包含功能：根据模板转换前端BillCard，参照翻译，显示公式处理）
//		    Object billcard = billCardOperator.toCard(rtnObj);
		    // 4、返回结果到前端
		    return resultVOs;
		}catch (BusinessException ex) {
			Logger.error(ex.getMessage(), ex);
			ExceptionUtils.wrapException(ex);
			return ex.getMessage();
		}
	}
	
	protected NccBillOperatorParam getRequestParam(IRequest request) {
	    // 解析request
	    String str = request.read();
	    IJson json = JsonFactory.create();
	    NccBillOperatorParam operaParam = json.fromJson(str, NccBillOperatorParam.class);
	    return operaParam;
	  }
	
	/**
	   * 提交指派处理
	   *
	   * @param commitVOs
	   * @param userobj 指派信息
	   * @return
	   * @throws BusinessException
	   */
	  protected Object commit(AggMonthOtTimeVO[] commitVOs, Object userobj)
	      throws BusinessException {
	    Object result = null;
	    // 判断是否定义审批流
	    boolean hasFlow = NCCFlowUtils.hasApproveflowDef(
	    		MonthOtTimeVOConst.CONST_BILLTYPE_COST, commitVOs[0]);
	    // 有，则走提交动作脚本
	    if (hasFlow) {
	      result = this.callActionScript(commitVOs, userobj);
	    }
	    // 没有，则提交即审批
	    else {
	      result = this.callAutoApproveActionScript(commitVOs);
	    }
	    return result;
	  }
	  
	  protected Object callActionScript(AggMonthOtTimeVO[] aggVOs,
		      Object content) throws BusinessException {

		    String actionCode = MonthOtTimeVOConst.CONST_ACTION_SAVE;
		    String billType = MonthOtTimeVOConst.CONST_BILLTYPE_COST;

		    CloudPFlowContext context = new CloudPFlowContext();
		    context.setActionName(actionCode);
		    context.setBillType(billType);
		    context.setBillVos(aggVOs);
		    // 指派信息不为空，则添加指派信息
		    if (content != null) {
		      Map<Object, Object> contentParam = new HashMap<>();
		      contentParam.put("content", content);
		      context.seteParam(contentParam);
		    }

		    Logger.debug("开始调用动作脚本 ActionName[" + actionCode + "] BillType[" + billType
		        + "]...");
		    ICloudScriptPFlowService service = CommonUtil.getCPFlowService();
		    Object[] result = service.exeScriptPFlow(context);

		    if ((result == null) || (result.length == 0) || (result[0] == null)) {
		      return null;
		    }

		    // begin 单提交指派功能
		    if (result[0] instanceof Map) {
		      Map map = (Map) result[0];
		      String type = String.valueOf(map.get(PfUtilBaseTools.PARAM_WORKFLOWTYPE));
		      if (PfUtilBaseTools.PARAM_APPROVEFLOW.equals(type)
		          || PfUtilBaseTools.PARAM_WORKFLOW.equals(type)) {
		        NccCommitReturnInfo returnInfo = new NccCommitReturnInfo();
		        returnInfo.setReturnMsg(map);
		        return returnInfo;
		      }
		    }
		    // end 单提交指派功能

		    // 多提交异常
		    if (result[0] instanceof PfProcessBatchRetObject) {
		      PfProcessBatchRetObject batchRetObject =
		          (PfProcessBatchRetObject) result[0];
		      String errMsg = batchRetObject.getExceptionMsg();
		      if ((errMsg != null) && !"".equals(errMsg)) {
		        ExceptionUtils.wrapBusinessException(errMsg);
		      }
		      return batchRetObject.getRetObj();
		    }

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

		  /**
		   * 提交即审批
		   *
		   * @param aggVO
		   * @return
		   * @throws BusinessException
		   */
		  protected Object callAutoApproveActionScript(AggMonthOtTimeVO[] aggVOs)
		      throws BusinessException {

		    String actionCode = this.getActionCode();
		    String billType = MonthOtTimeVOConst.CONST_BILLTYPE_COST;
		    Map<Object, Object> extParam = new HashMap<Object, Object>();
		    extParam.put("IS_RELOADBILL", true);

		    // 调用提交即审批接口
		    CloudPFlowContext context = new CloudPFlowContext();
		    context.seteParam(extParam);
		    context.setActionName(actionCode);
		    context.setBillType(billType);
		    context.setBillVos(aggVOs);

		    Logger.debug("开始调用动作脚本 ActionName[" + actionCode + "] BillType[" + billType
		        + "]...");
		    ICloudScriptPFlowService service = CommonUtil.getCPFlowService();
		    Object[] result = service.exeScriptPFlow_CommitNoFlowBatch(context);

		    if ((result == null) || (result.length == 0) || (result[0] == null)) {
		      return null;
		    }
		    if (result[0] instanceof PfProcessBatchRetObject) {
		      PfProcessBatchRetObject batchRetObject =
		          (PfProcessBatchRetObject) result[0];
		      String errMsg = batchRetObject.getExceptionMsg();
		      // 没有异常信息则表明执行成功
		      if ((errMsg != null) && !"".equals(errMsg)) {
		        ExceptionUtils.wrapBusinessException(errMsg);
		      }
		      return batchRetObject.getRetObj();
		    }
		    Logger.debug(
		        "调用动作脚本 ActionName[" + actionCode + "] BillType[" + billType + "]结束");
		    return result;
		  }

	
	/**
	   * 动作编码
	   *
	   * @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);
	        }
	      }
	    }
//	    PsnJobVO psnjobVO = AttendDataUtil.queryPsnJob(null);
//	    String pk_psndoc = (String) parent.getAttributeValue(MonthOtTimeVO.PK_PSNDOC);
//	    if(StringUtils.isNotBlank(pk_psndoc)) {
//	    	psnjobVO = AttendDataUtil.queryPsnJob(pk_psndoc);
//	    }
		PsnJobVO psnjobVO = AttendDataUtil.queryPsnJob(null);
		nc.vo.hrkq.monthottime.MonthOtTimeVO parent = vo.getParentVO();
	    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);
	    }
		String pk_psndoc = (String) parent.getAttributeValue(MonthOtTimeVO.PK_PSNDOC);
	    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);
//	    			加班日期类型按次	参照名称
//	    			加班日期	日期格式：YYYY-MM-DD
//	    			加班次数	数值，一位小数
//	    			加班说明	
	    			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.OTTIMES) == null ? "" :  new UFDouble(bvo.getAttributeValue(MonthOtTimeBVO.OTTIMES).toString(),1)+"");
	    			note.append("<br>加班说明:").append(bvo.getAttributeValue(MonthOtTimeBVO.OTDESCRIPTION) == null ? "" : bvo.getAttributeValue(MonthOtTimeBVO.OTDESCRIPTION).toString() +"");
	    		}else if("2".equals(otapplytype)) {//普通
	    			type = (String) bvo.getAttributeValue(MonthOtTimeBVO.OTDATETYPE);
//	    			加班日期类型	参照名称
//	    			加班日期	日期格式：YYYY-MM-DD
//	    			开始时间	日期格式：YYYY-MM-DD HH:MM:SS
//	    			结束时间	日期格式：YYYY-MM-DD HH:MM:SS
//	    			加班时长小时	数值，一位小数
//	    			加班费时长	数值，一位小数
//	    			调休时长	数值，一位小数
//	    			加班说明	
	    			note.append("<br>加班日期类型:").append(typeMap.get(bvo.getAttributeValue(MonthOtTimeBVO.OTDATETYPE))+"\n");
	    			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() +"");
	    		}
	    		
	    		bvo.setAttributeValue("note", note.toString());
	    		
	    		if(bvo.getAttributeValue(MonthOtTimeBVO.OTDATE) == null) {
	    			continue;
	    		}
	    		UFDate otdate = new UFDate(bvo.getAttributeValue(MonthOtTimeBVO.OTDATE).toString());//加班日期是否为节假日
	    		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("加班时间范围内存在冲突的加班单据");
		    }
		    
		    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;
    }
	
	public void setValue(MonthOtTimeVO vo,PsnJobVO psnJob,String appCode) throws BusinessException{
		if("606570D0".equals(appCode)) {
			//按次
			vo.setOtapplytype("1");
			vo.setAttributeValue("otapplytype", "1");
		}else if("606570C0".equals(appCode) || "606570E0".equals(appCode)) {
			//普通
			vo.setOtapplytype("2");
			vo.setAttributeValue("otapplytype", "2");
		}
	}

}
