package nc.bs.pu.wgpt.process;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import nc.bs.dao.BaseDAO;
import nc.bs.framework.common.InvocationInfoProxy;
import nc.bs.framework.common.NCLocator;
import nc.bs.pf.pub.PfDataCache;
import nc.bs.uap.tools.formula.ExtFormulaParser;
import nc.itf.pu.invoke.IMatrilFpService;
import nc.itf.pu.m21.IOrderPayPlanQuery;
import nc.itf.pu.m21.IOrderQuery;
import nc.itf.uap.pf.IPfExchangeService;
import nc.itf.uap.pf.IWorkflowDefine;
import nc.itf.uap.pf.metadata.IFlowBizItf;
import nc.jdbc.framework.SQLParameter;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.jdbc.framework.processor.ResultSetProcessor;
import nc.net.servlet.IReturnStatus;
import nc.pub.sap.constant.SapConstants;
import nc.uap.pf.metadata.PfMetadataTools;
import nc.ui.ml.NCLangRes;
import nc.util.mmf.framework.base.MMValueConvert;
import nc.util.uap.wgpt.WuYeWgptUtil;
import nc.vo.arap.pay.AggPayBillVO;
import nc.vo.arap.pay.PayBillItemVO;
import nc.vo.arap.pay.PayBillVO;
import nc.vo.esb.ResultEsbVO;
import nc.vo.esb.ResultVO;
import nc.vo.fi.pub.SqlUtils;
import nc.vo.fipub.exception.ExceptionHandler;
import nc.vo.pu.m21.entity.AggPayPlanVO;
import nc.vo.pu.m21.entity.OrderHeaderVO;
import nc.vo.pu.m21.entity.OrderItemVO;
import nc.vo.pu.m21.entity.OrderVO;
import nc.vo.pu.m21.entity.PayPlanVO;
import nc.vo.pu.pub.util.ArrayUtil;
import nc.vo.pub.AggregatedValueObject;
import nc.vo.pub.BusinessException;
import nc.vo.pub.ISuperVO;
import nc.vo.pub.compiler.PfParameterVO;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pub.workflownote.WorkflownoteVO;
import nc.vo.pubapp.AppContext;
import nc.vo.pubapp.pattern.data.ValueUtils;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nc.vo.pubapp.pattern.pub.MathTool;
import nc.vo.tmpub.util.MathUtil;
import nc.vo.uap.pf.PFRuntimeException;
import nc.vo.wfengine.core.workflow.WorkflowProcess;
import nc.vo.wfengine.definition.WorkflowTypeEnum;
import nc.vo.wgpt.log.WuYeWgptLogVO;
import ncc.bs.wy.tools.WyWGPTJsonTools;
import ncc.itf.wgpt.fkd.IWuyeWGPTPaybill;
import ncc.pub.wywgpt.utils.WyWGPTUtils;
import nccloud.vo.pf.flowinstance.NCCFlowInstanceVO;
import uap.json.JSONObject;

/**
 * @Description: 【网购平台->NC】新增采购订单+付款计划
 * 
 * @author 谢文如 【碧桂园-物业板块-网购平台接口】
 * @date 2019-3-28
 * @version with NCC
 */
public class WriteOrderInfoProcess {

	public String writeOrderInfo(JSONObject jsonobj) throws BusinessException {
		String rsdata = null;
		String pk_order = null;
		Object wgptbillcode = null;
		ResultEsbVO<ResultVO> esb = new ResultEsbVO<ResultVO>();
		ResultVO result = new ResultVO();
		result.setResult("");
		esb.setResultInfo(result);
		try {
			BaseDAO baseDAO = new BaseDAO();
			if (jsonobj == null || "".equals(jsonobj)) {// 无Post提交值
				result.setCode(IReturnStatus.FAILING);// 失败
				result.setMessage("Post所提交请求Json格式错误或者无值!");
				WuYeWgptUtil.createResultEsbVO(esb);
				esb.getEsbInfo().setReturnStatus(IReturnStatus.ESB_FAILING);
				esb.getEsbInfo().setReturnMsg("失败");
				esb.setResultInfo(result);
			} else {
				/** begin 获取请求值 **/
				JSONObject obj = jsonobj.getJSONObject("requestInfo");
				JSONObject header = obj.getJSONObject("Header");
				boolean isExistPayPlan = obj.isNull("OrderPayPlan");

				wgptbillcode = header.get("vdef19");

				if (null != wgptbillcode) {
					String sql = "select pk_order from  po_order where nvl(dr,0)=0 and vdef15='" + wgptbillcode + "'";
					pk_order = (String) baseDAO.executeQuery(sql, new ColumnProcessor());
					if (null != pk_order && isExistPayPlan) {
						result.setCode(IReturnStatus.FAILING);
						result.setMessage("NC系统已存在网购平台单号为:" + wgptbillcode + "的采购订单,请勿重复传递!");
						WuYeWgptUtil.createResultEsbVO(esb);
						esb.getEsbInfo().setReturnStatus(IReturnStatus.ESB_FAILING);
						esb.getEsbInfo().setReturnMsg("失败");
						esb.setResultInfo(result);
					} else {

						OrderVO orderVO = WyWGPTJsonTools.jsonToOrderVO(jsonobj, OrderVO.class, OrderHeaderVO.class, OrderItemVO.class, PayPlanVO.class);
						/**
						 * add by 添加物业仓库的校验  begin
						 */
						OrderItemVO[] itemVOs =orderVO.getBVO().clone();
						
						String reqstordoc=null;
						SQLParameter parameter=null;
						String countsql="select count(doc.pk_stordoc) from bd_stordoc doc left join org_orgs o on doc.pk_org = o.pk_org where doc.def3 = ?  and o.code = ?  and o.isbusinessunit = 'Y' and doc.dr=0";
						for(int i=0;i<itemVOs.length;i++){
							reqstordoc=itemVOs[i].getPk_reqstordoc();
							if(!"ZCC".equals(reqstordoc)){
								parameter=new SQLParameter();
								parameter.addParam(itemVOs[i].getVbdef3());
								parameter.addParam(itemVOs[i].getPk_reqstoorg_v());
								Object object =baseDAO.executeQuery(countsql, parameter, new ColumnProcessor());
								if(ValueUtils.getInt(object)>1){
									ExceptionUtils.wrappBusinessException("人力组织："+itemVOs[i].getVbdef3()+"分配了多个仓库！");
								}
							}
						}
						/**
						 * add by 添加物业仓库的校验  end
						 */
						ISuperVO[] payplanISuperVOs = orderVO.getChildren(PayPlanVO.class);
						orderVO.setChildren(PayPlanVO.class, null);
						/**
						 * add by 分开执行公式   begin
						 */
						orderVO.setBVO(null);
						// 转换前非空校验、执行公式、翻译后各项非空校验
						WyWGPTUtils.notNullCheckAndExFormula("WY21_HEAD", "WY21_BODY", orderVO);
						
						HashMap<String, ArrayList<String>> itemConfigMap = WyWGPTUtils.getFormulas("WY21_BODY", SapConstants.DIRECTION_SAP2NC);
						ArrayList<String> itemFormulaList = itemConfigMap.get(SapConstants.FORMULA_KEY);

						ExtFormulaParser extItemFormulaParser = new ExtFormulaParser();
						
						List<OrderItemVO> extItemVOs=new ArrayList<OrderItemVO>();
						String[] itemFormulas = itemFormulaList.toArray(new String[0]);
						for(int item=0;item<itemVOs.length;item++){
							orderVO.setBVO(new OrderItemVO[]{itemVOs[item]});
							extItemFormulaParser.execFormulas(itemFormulas, orderVO, false);
							extItemVOs.add(orderVO.getBVO()[0]);
						}
						orderVO.setBVO(extItemVOs.toArray(new OrderItemVO[0]));
						/**
						 * add by 分开执行公式   end
						 */
						Object saveOrderVo = null;
						if (null == pk_order) {
							//物料自动分配
							((IMatrilFpService)NCLocator.getInstance().lookup(IMatrilFpService.class)).matrialFp(orderVO.getBVO());
							// 保存订单
							saveOrderVo = WyWGPTUtils.getIPFBusiAction().processAction("SAVEBASE", orderVO.getHVO().getVtrantypecode(), null, orderVO, null, null);
							IOrderQuery orderQuery=NCLocator.getInstance().lookup(IOrderQuery.class);
							OrderVO[] orderVOs =orderQuery.queryOrderVOsByIds(new String[]{((OrderVO[]) saveOrderVo)[0].getPrimaryKey()}, UFBoolean.FALSE);
							// 提交订单
							saveOrderVo = WyWGPTUtils.getIPFBusiAction().processAction("SAVE", orderVOs[0].getHVO().getVtrantypecode(), null, orderVOs[0], null, null);
							String userID = WyWGPTUtils.queryWorkUserID(orderVOs[0].getHVO().getVtrantypecode(), ((OrderVO[]) saveOrderVo)[0].getPrimaryKey());
							OrderHeaderVO headerVO = ((OrderVO[]) saveOrderVo)[0].getHVO();
							headerVO.setApprover(userID);
							HashMap<String, Object> eParam = new HashMap<String, Object>();
							eParam.put("notechecked", "notechecked");
							eParam.put("besideapprove", null);
							pk_order = headerVO.getPrimaryKey();
							WorkflownoteVO worknoteVO = WyWGPTUtils.getWorkflownoteVO("APPROVE" + userID, orderVO.getHVO().getVtrantypecode(), ((OrderVO[]) saveOrderVo)[0], eParam);
							// 审批订单
							WyWGPTUtils.getIPFBusiAction().processAction("APPROVE", orderVO.getHVO().getVtrantypecode(), worknoteVO, ((OrderVO[]) saveOrderVo)[0], null, eParam);
						}
						orderVO.setChildren(PayPlanVO.class, payplanISuperVOs);
						if (null != orderVO.getChildren(PayPlanVO.class)) {
							HashMap<String, ArrayList<String>> bodyConfigMap = WyWGPTUtils.getFormulas("WY21_PAYPLAN", SapConstants.DIRECTION_SAP2NC);
							ArrayList<String> bodyFormulaList = bodyConfigMap.get(SapConstants.FORMULA_KEY);
							String[] bodyFormulas = bodyFormulaList.toArray(new String[0]);

							IOrderPayPlanQuery orderPayPlanQuery = NCLocator.getInstance().lookup(IOrderPayPlanQuery.class);
							AggPayPlanVO[] aggPayPlanVOs = orderPayPlanQuery.queryPayPlanVOs(new String[] { saveOrderVo == null ? pk_order.toString()
									: ((OrderVO[]) saveOrderVo)[0].getPrimaryKey() });
							List<PayPlanVO> insertPayPlanVOs = new ArrayList<PayPlanVO>();
							PayPlanVO newPayPlanVO = null;
							PayPlanVO oldPayPlanVO = (PayPlanVO) aggPayPlanVOs[0].getPayPlanVO()[0];
							UFDouble totalNrate=UFDouble.ZERO_DBL;
							for (int i = 0; i < orderVO.getChildren(PayPlanVO.class).length; i++) {
								newPayPlanVO = (PayPlanVO) orderVO.getChildren(PayPlanVO.class)[i];
								newPayPlanVO.setPk_group(oldPayPlanVO.getPk_group());
								newPayPlanVO.setPk_order(oldPayPlanVO.getPk_order());
								newPayPlanVO.setPk_financeorg(oldPayPlanVO.getPk_financeorg());
								newPayPlanVO.setPk_financeorg_v(oldPayPlanVO.getPk_financeorg_v());
								newPayPlanVO.setDr(0);
								totalNrate=MathUtil.add(totalNrate,newPayPlanVO.getNrate());
								insertPayPlanVOs.add(newPayPlanVO);
								
								if((i+1)==orderVO.getChildren(PayPlanVO.class).length) {
									//如果生成的付款计划比例不是100%就把剩下的生成一行
									UFDouble  surplusrate=MathUtil.sub(new UFDouble(100), totalNrate);
									if(surplusrate!=UFDouble.ZERO_DBL) {
										PayPlanVO  surplusPayPlanVO=(PayPlanVO) newPayPlanVO.clone();
										surplusPayPlanVO.setNrate(surplusrate);
										surplusPayPlanVO.setCrowno(MMValueConvert.toInteger(((i+1)*10+10)).toString());
										surplusPayPlanVO.setNtotalorigmny(orderVO.getHVO().getNtotalorigmny());
										UFDouble mny =orderVO.getHVO().getNtotalorigmny().multiply(surplusrate).div(100);
										surplusPayPlanVO.setNorigmny(mny.setScale(2, UFDouble.ROUND_HALF_UP));
										surplusPayPlanVO.setNmny(mny.setScale(2, UFDouble.ROUND_HALF_UP));
										insertPayPlanVOs.add(surplusPayPlanVO);
									}
								}
							}
							baseDAO.deleteVOArray(aggPayPlanVOs[0].getPayPlanVO());
							aggPayPlanVOs[0].setPayPlanVO(insertPayPlanVOs.toArray(new PayPlanVO[0]));
							ExtFormulaParser extFormulaParser = new ExtFormulaParser();
							extFormulaParser.execFormulas(bodyFormulas, aggPayPlanVOs[0], false);
							baseDAO.insertVOList(insertPayPlanVOs);
							aggPayPlanVOs = orderPayPlanQuery.queryPayPlanVOs(new String[] { saveOrderVo == null ? pk_order.toString()
									: ((OrderVO[]) saveOrderVo)[0].getPrimaryKey() });
							pushToPayBill(aggPayPlanVOs[0]);
						}
						//保存订单后前回写累计申请付款金额
//						UFDouble ntotalorigmny = orderVO.getHVO().getNtotalorigmny();//价税合计
//						UFDouble nrate = (UFDouble) payplanISuperVOs[0].getAttributeValue("nrate");
//						if(null != ntotalorigmny && null != nrate) {
//							UFDouble naccpaymny= ntotalorigmny.multiply(nrate).div(100);
//							String sqlmny = "update po_order set naccpaymny='"+naccpaymny+"' where nvl(dr,0)=0 and vdef15='" + wgptbillcode + "'";
//						    new BaseDAO().executeUpdate(sqlmny);
//						}
						result.setCode(IReturnStatus.SUCCEED);// 成功
						result.setMessage("传递物业采购订单成功");
						WuYeWgptUtil.createResultEsbVO(esb);
						esb.setResultInfo(result);
					}
				}

			}
		} catch (Exception e) {
			result.setCode(IReturnStatus.ERROR);// 异常
			result.setError(WuYeWgptUtil.getExceptionDetail(e));
			result.setMessage(result.getError());
			WuYeWgptUtil.createResultEsbVO(esb);// 初始化响应对象
			esb.getEsbInfo().setReturnStatus(IReturnStatus.ESB_ERROR);
			esb.getEsbInfo().setReturnMsg("异常");
			esb.setResultInfo(result);// 设置响应内容
			ExceptionUtils.marsh(e);
		} finally {
			rsdata = com.alibaba.fastjson.JSONObject.toJSONString(esb);

			WuYeWgptLogVO logVO = new WuYeWgptLogVO();
			logVO.setNc_id(pk_order);
			logVO.setOther_id(wgptbillcode + "");
			logVO.setBillno("");
			logVO.setTranstypecode("21");
			logVO.setItfcode("WGPT-NC-001");
			logVO.setItfname("【网购平台->NC】新增采购订单+付款计划");
			logVO.setBilldata(jsonobj == null ? "" : jsonobj.toString());
			logVO.setRsdata(rsdata);
			logVO.setMsg(null);
			logVO.setIssuccess(IReturnStatus.SUCCEED.equals(result.getCode()) ? "Y" : "N");

			WuYeWgptUtil.getIWuYeWgptLogService().insertLog_RequiresNew(logVO);

		}
		return rsdata;
	}
	
	private static boolean hasApproveflowDef(String transOrBiiType, AggregatedValueObject billVo) throws Exception {
		IFlowBizItf fbi = (IFlowBizItf) PfMetadataTools.getBizItfImpl(billVo, nc.itf.uap.pf.metadata.IFlowBizItf.class);
		if (fbi == null) {
			throw new PFRuntimeException("没有实现IFlowBizItf接口");
		}

		IWorkflowDefine wfDefine = NCLocator.getInstance().lookup(nc.itf.uap.pf.IWorkflowDefine.class);
		boolean isStepIntoFlow = wfDefine.queryIsStepIntoFlow(billVo.getParentVO().getPrimaryKey(), transOrBiiType, null);
		if (isStepIntoFlow) {
			NCCFlowInstanceVO resultInstance[] = NCLocator.getInstance()
					.lookup(nc.itf.pub.workflowqry.IFlowInstanceQuery.class)
					.findFlowInstancesByBillIdAndBillTypeAppendOrderByCondition(billVo.getParentVO().getPrimaryKey(),
							transOrBiiType);
			WorkflowProcess wf = PfDataCache.getWorkflowProcess(resultInstance[0].getProcessdefid());
			if (wf != null && wf.getActivities().size() == 1) {
				return false;
			}
		}
		boolean hasApproveFlow = false;
		hasApproveFlow = wfDefine.hasValidProcessDef(InvocationInfoProxy.getInstance().getGroupId(), transOrBiiType,
				fbi.getPkorg(), fbi.getBillMaker(), fbi.getEmendEnum().intValue(),
				WorkflowTypeEnum.Approveflow.getIntValue());
		boolean hasWorkfFlow = false;
		hasWorkfFlow = wfDefine.hasValidProcessDef(InvocationInfoProxy.getInstance().getGroupId(), transOrBiiType,
				fbi.getPkorg(), fbi.getBillMaker(), fbi.getEmendEnum().intValue(),
				WorkflowTypeEnum.Workflow.getIntValue());
		return isStepIntoFlow || hasApproveFlow || hasWorkfFlow;
	}
	
	/**新加方法，采购付款计划自动推出付款单
	 * @time 2019-5-10
	 * @param aggPayPlanVO
	 * @throws Exception 
	 */
	public void pushToPayBill(AggPayPlanVO aggPayPlanVO) throws Exception{
		List<Object> list = new ArrayList<Object>();
		setNcanpayMny(aggPayPlanVO, list);
		checkIfPay(aggPayPlanVO);
		AggregatedValueObject[] destVOs =getDestVOs(list.toArray(new Object[list.size()]));
		destVOs=convertVOs(destVOs);
		HashMap<String, String> eParam = new HashMap<String, String>();
		eParam.put("notechecked", "notechecked");
		eParam.put("besideapprove", null);
//		SapUtils.getIPFBusiAction().processAction("SAVE", destVOs[0].getParentVO().getAttributeValue("pk_tradetype").toString(), null, destVOs[0], null, eParam);
		NCLocator.getInstance().lookup(IWuyeWGPTPaybill.class).savePaybillToWGPT(destVOs,eParam);
	}

	/**新加方法，校验采购订单是否已经生成付款单
	 * @time 2019-5-10
	 * @param aggPayPlanVO
	 * @throws Exception 
	 */
	private void checkIfPay(AggPayPlanVO aggPayPlanVO) throws Exception{
		Map<String, String> billNo = new HashMap<String, String>();
		billNo.put(aggPayPlanVO.getHVO().getPk_order(), aggPayPlanVO.getHVO().getVbillcode());
		StringBuilder sqlBuilder = new StringBuilder();
		sqlBuilder.append("select pk_paybill,src_billid");
		sqlBuilder.append(" from ").append((new PayBillItemVO()).getTableName());
		sqlBuilder.append(" where ");
		sqlBuilder.append(" nvl(dr,0)=0 and ");
		try {
			sqlBuilder.append(SqlUtils.getInStr("src_billid", billNo.keySet().toArray(new String[0]), true));
		} catch (BusinessException arg5) {
			ExceptionHandler.consume(arg5);
			sqlBuilder.append(" 1 = 1");
		}
		final HashMap ret = new HashMap();

		BaseDAO baseDAO=new BaseDAO();
		baseDAO.executeQuery(sqlBuilder.toString(), new ResultSetProcessor() {

			private static final long serialVersionUID = 1L;

			public Object handleResultSet(ResultSet rs) throws SQLException {
				while(rs.next()) {
					ret.put(rs.getString("pk_paybill"), rs.getString("src_billid"));
				}

				return null;
			}
		});

		if(ret.size()>0){
			ExceptionUtils.wrappBusinessException("订单已生成付款单！");
		}
}

/**新加方法，计算设值付款金额
 * @time 2019-5-10
 * @param aggPayPlanVO
 * @param list
 * @return
 */
private boolean setNcanpayMny(AggPayPlanVO aggPayPlanVO, List<Object> list) {
	PayPlanVO vo=aggPayPlanVO.getPayPlanVO()[0];
	if (UFDouble.ZERO_DBL.equals(vo.getNorigmny())
			|| MathTool.greaterThan(UFDouble.ZERO_DBL, vo.getNorigmny())) {
		String rows = vo.getCrowno();
		ExceptionUtils.wrappBusinessException(NCLangRes.getInstance().getStrByID(
				"4001001_0", "04001001-0266", null, new String[] {
						rows
				})/* {0}行原币金额小于等于0，不能付款。 */);
	}
	UFDouble ncanpayorgmny =
			MathTool.sub(vo.getNorigmny(), vo.getNaccumpayorgmny());
	if (MathTool.compareTo(ncanpayorgmny, UFDouble.ZERO_DBL) <= 0) {
		return false;
	}
	vo.setNorigmny(ncanpayorgmny);
	vo.setNmny(MathTool.sub(vo.getNmny(), vo.getNaccumpaymny()));
	aggPayPlanVO.setPayPlanVO(new PayPlanVO[]{vo});
	list.add(aggPayPlanVO);
	return true;
}

/**新加方法，单据转换
 * @time 2019-5-10
 */
private AggregatedValueObject[] getDestVOs(Object[] objs) throws BusinessException {
	AggPayPlanVO[] vos = ArrayUtil.convertArrayType(objs);
	//		    AggPayPlanVO[] vos = PayPlanViewVO.getAggPayPlanVO(views);
	AggregatedValueObject[] destVOs = ((IPfExchangeService)NCLocator.getInstance().lookup(IPfExchangeService.class)).runChangeDataAryNeedClassify("21", "F3", vos, (PfParameterVO)null, 1);
	return this.convertVOs(destVOs);
}

/**单据VO信息填充
 * @time 2019-5-10
 * @param destVOs
 * @return
 */
private AggregatedValueObject[] convertVOs(AggregatedValueObject[] destVOs) {
	if (null == destVOs) {
		return null;
	}
	AggPayBillVO vo = new AggPayBillVO();

	PayBillVO headVO = ((AggPayBillVO) destVOs[0]).getHeadVO();
	UFDate busidate = AppContext.getInstance().getBusiDate();
	headVO.setBilldate(busidate);
	vo.setParentVO(headVO);

	List<PayBillItemVO> list = new ArrayList<PayBillItemVO>();
	for (AggregatedValueObject destVO : destVOs) {
		PayBillItemVO[] itemVOs = ((AggPayBillVO) destVO).getBodyVOs();
		list.addAll(Arrays.asList(itemVOs));
	}
	PayBillItemVO[] allItemVOs = list.toArray(new PayBillItemVO[list.size()]);

	for (PayBillItemVO itemVO : allItemVOs) {
		itemVO.setBilldate(busidate);
	}
	vo.setChildrenVO(allItemVOs);
	return new AggregatedValueObject[] {
			vo
	};
}

}
