package nccloud.hrkq.hrkq.monthottimevo.action;

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

import org.apache.commons.lang3.StringUtils;

import nc.bs.logging.Logger;
import nc.itf.om.IPostQueryService;
import nc.md.persist.framework.IMDPersistenceQueryService;
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.om.post.AggPostVO;
import nc.vo.om.post.PostVO;
import nc.vo.pf.change.PfUtilBaseTools;
import nc.vo.pf.pub.util.SQLUtil;
import nc.vo.pub.BusinessException;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFDateTime;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pubapp.pattern.model.entity.bill.AbstractBill;
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.json.JsonFactory;
import nccloud.framework.web.ui.pattern.billcard.BillCard;
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.hrkq.common.utils.AttendDataUtil;
import nccloud.web.workflow.approve.util.NCCFlowUtils;

public class MonthOtTimeVOCommitAction implements ICommonAction{

	@Override
	  public Object doAction(IRequest request) {
	    // 获取前端请求参数
	    NccBillOperatorParam operaParam = this.getRequestParam(request);
	    Object result = null;
	    try {
	      // 根据pk查询待操作单据
	    	AggMonthOtTimeVO[] operaVOs = this.queryBillsByPks(operaParam);
	      // ts赋值
	      CommonUtil.setBillsTs(operaParam.getPkMapTs(), operaVOs);
	      PsnJobVO psnjobVO = AttendDataUtil.queryPsnJob(null);
	      String pk_post = psnjobVO.getPk_post();
		  if(StringUtils.isNotBlank(pk_post)) {
			  AggPostVO aggPostVO = ServiceLocator.find(IPostQueryService.class).queryByPk(pk_post);
			  if(aggPostVO != null) {
				  PostVO postVO = (PostVO) aggPostVO.getParentVO();
				  Object glbdef1 = postVO.getAttributeValue("glbdef1");
				  if(glbdef1 == null || !UFBoolean.valueOf(glbdef1.toString()).booleanValue()) {
					  doBefore(operaVOs);
				  }
			  }
		  }
	      
	      // 对查询结果执行具体业务处理
	      Object resultVOs = this.commit(operaVOs, operaParam.getUserObj());
	      // 卡片页面需要返回操作后的数据到前端，列表界面操作后，前端重新调用列表查询请求，无需返回操作后数据，所以此处按照卡片处理返回结果
	      result = this.buildFontResult(operaParam, resultVOs);
	    }
	    catch (BusinessException ex) {
	      Logger.error(ex.getMessage(), ex);
	      ExceptionUtils.wrapException(ex);
	    }
	    return result;
	  }
	
	  private void doBefore(AggMonthOtTimeVO[] aggvos) throws BusinessException {
		  String msg = "";
		  IMonthottimevoMaintain service = CommonUtil.getMaintainService();
		  Boolean checkFlag = Boolean.FALSE;
		  for(AggMonthOtTimeVO aggvo : aggvos) {
			  MonthOtTimeVO vo = aggvo.getParentVO();
			  String otapplytype = (String) vo.getAttributeValue(MonthOtTimeVO.OTAPPLYTYPE);
			  if("1".equals(otapplytype)) {
				  continue;
			  }
			  String pk_psndoc = (String) vo.getAttributeValue(MonthOtTimeVO.PK_PSNDOC);
			  Map<String, UFDouble> map = service.queryMonth(pk_psndoc);
			  UFDouble totalHours = UFDouble.ZERO_DBL;
			  MonthOtTimeBVO[] bvos = (MonthOtTimeBVO[]) aggvo.getChildrenVO();
			  for(MonthOtTimeBVO bvo : bvos) {
				  UFDate otdate = bvo.getAttributeValue(MonthOtTimeBVO.OTDATE) == null ? ((UFDateTime)bvo.getAttributeValue(MonthOtTimeBVO.OVERTIMEBEGINTIME)).getDate() : (UFDate) bvo.getAttributeValue(MonthOtTimeBVO.OTDATE);
				  if(otdate != null) {
					  String monthday = dateToStr(otdate);
					  UFDouble hours = map == null || map.size() == 0 || map.get(monthday) == null ? UFDouble.ZERO_DBL : map.get(monthday);
	//				  totalHours = hours.add(new UFDouble(bvo.getAttributeValue(MonthOtTimeBVO.OTHOURS).toString()));
					  UFDouble othours = bvo.getAttributeValue(MonthOtTimeBVO.OTHOURS) == null ? UFDouble.ZERO_DBL : (UFDouble) bvo.getAttributeValue(MonthOtTimeBVO.OTHOURS);
					  totalHours = hours.add(othours);
					  if(totalHours.toDouble() > 36) {
						  checkFlag = Boolean.TRUE;
					  } else {
						  map.put(monthday, totalHours);
					  }
				  }
			  }
		  }
		  if(checkFlag) {
			  throw new BusinessException("本月加班时长超过36小时，不允许发起申请");
		  }
	  }
	  
	  public String DATE_FORMAT_Y_M_DHM = "yyyy-MM";
	  public String dateToStr(UFDate date) {
	      String strDate = "";
	      SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_Y_M_DHM);
	      strDate = sdf.format(date.toDate());
	      return strDate;
	  }

	  protected Object buildFontResult(NccBillOperatorParam operaParam,
	      Object result) {
	    // 指派处理
	    if (result instanceof NccCommitReturnInfo) {
	      NccCommitReturnInfo returnvo = (NccCommitReturnInfo) result;
	      return returnvo.getReturnMsg();
	    }

	    AbstractBill[] resultVOs = (AbstractBill[]) result;
	    if (resultVOs.length == 1) {
	      BillCardOperator billCardOperator =
	          new BillCardOperator(operaParam.getPageCode());
	      BillCard card = billCardOperator.toCard(resultVOs[0]);
	      return card;
	    }

	    return null;
	  }

	  protected Object callActionScript(AggMonthOtTimeVO[] aggVOs,
	      Object content) throws BusinessException {

	    String actionCode = this.getActionCode();
	    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;
	  }

	  /**
	   * 提交指派处理
	   *
	   * @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;
	  }

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

	  protected NccBillOperatorParam getRequestParam(IRequest request) {
	    // 解析request
	    String str = request.read();
	    IJson json = JsonFactory.create();
	    NccBillOperatorParam operaParam = json.fromJson(str, NccBillOperatorParam.class);
	    return operaParam;
	  }

	  protected AggMonthOtTimeVO[] queryBillsByPks(NccBillOperatorParam operaParam)
	      throws BusinessException {
		  AggMonthOtTimeVO[] vos = null;
	    String[] pks = operaParam.getPks();
	    if (pks.length != 0) {
	      // 根据参数查询结果
	      IMDPersistenceQueryService service =
	          CommonUtil.getMDQueryService();
	      String wheresql = SQLUtil
	          .buildSqlForIn(MonthOtTimeVOConst.CONST_PARENT_PRIMARYKEY, pks);
	      Collection<AggMonthOtTimeVO> bills = service.queryBillOfVOByCond(
	    		  AggMonthOtTimeVO.class, wheresql, true, false);
	      if ((bills == null) || (bills.size() != pks.length)) {
	        ExceptionUtils.wrapBusinessException("单据已被修改，请刷新页面后重试");
	      }
	      
	      AggMonthOtTimeVO[] aggvos = bills.toArray(new AggMonthOtTimeVO[0]);
	      for(AggMonthOtTimeVO aggvo : aggvos) {
	      	 Collection<MonthOtTimeBVO> bbills =
	      	            service.queryBillOfVOByCond(MonthOtTimeBVO.class, "pk_monthottime ='"+aggvo.getParentVO().getAttributeValue("pk_monthottime")+"'", true,
	      	                false);
	      	 aggvo.setChildrenVO(bbills.toArray(new MonthOtTimeBVO[0]));
	      }
	      vos = bills.toArray(new AggMonthOtTimeVO[0]);
	    }
	    return vos;
	  }

}
