package ncc.bs.arap.myutil;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import nc.bs.framework.common.NCLocator;
import nc.bs.uap.tools.formula.ExtFormulaParser;
import nc.itf.uap.IUAPQueryBS;
import nc.pub.sap.constant.SapConstants;
import nc.pub.sap.sort.SapVOSort;
import nc.util.mmf.framework.base.MMValueCheck;
import nc.vo.cmp.bill.RecBillDetailVO;
import nc.vo.cmp.bill.RecBillVO;
import nc.vo.ep.bx.BXVO;
import nc.vo.erm.costshare.CShareDetailVO;
import nc.vo.pub.AggregatedValueObject;
import nc.vo.pub.BusinessException;
import nc.vo.pub.CircularlyAccessibleValueObject;
import nc.vo.pub.IAttributeMeta;
import nc.vo.pub.SuperVO;
import nc.vo.pub.VOStatus;
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.meta.entity.vo.Attribute;
import nc.vo.sap.syproconfig.SyProConfigBVO;
import nccloud.commons.collections.CollectionUtils;
import nccloud.commons.lang.StringUtils;
import uap.json.JSONArray;
import uap.json.JSONObject;

public class MYArapItfUtil {

	public static IUAPQueryBS getQueryBS() {
		return NCLocator.getInstance().lookup(IUAPQueryBS.class);
	}
	public static <T extends AggregatedValueObject> T jsonToAggVO (
			Object billdata,Class<? extends AggregatedValueObject> aggVOClass, Class<? extends CircularlyAccessibleValueObject> headVOClass, Class<? extends CircularlyAccessibleValueObject> bodyVOClass)throws Exception{		
		JSONObject data=new JSONObject();	
		if(billdata instanceof String){
			JSONObject jsonObj = new JSONObject((String)billdata);
			data = (JSONObject) jsonObj.get("data");
		}else if(billdata instanceof JSONObject){
			data=(JSONObject)billdata;
		}
		T aggVO = null;
		try {
			if(data == null||MMValueCheck.isEmpty(data.toString())) {
				return null;
			}
			aggVO = (T) aggVOClass.newInstance();
			CircularlyAccessibleValueObject headVO;
			CircularlyAccessibleValueObject[] bodyVOs;
			CircularlyAccessibleValueObject bodyVO;
			JSONObject bodyJsonObj;
			JSONObject head = (JSONObject) data.get("headitem");
			JSONArray bodyitems = (JSONArray) data.get("bodyitems");			
			if (head == null || bodyitems == null) {
				return null;
			}
			headVO = headVOClass.newInstance();
			//表头设值
			if(headVO instanceof RecBillVO){
				setRecValue(headVOClass,headVO,head);
			}else{
				setValue(headVOClass,headVO,head);
			}			
			//表体VO
			bodyVOs =(CircularlyAccessibleValueObject[]) Array.newInstance(bodyVOClass,bodyitems.length());
			for (int j = 0; j < bodyitems.length(); j++) {
				bodyJsonObj = (JSONObject) bodyitems.get(j);
				if (bodyJsonObj == null) {
					continue;
				}
				bodyVO = bodyVOClass.newInstance();
				//表体设值
				if(bodyVO instanceof RecBillDetailVO){
					setRecValue(bodyVOClass, bodyVO, bodyJsonObj);
				}else{
					setValue(bodyVOClass, bodyVO, bodyJsonObj);	
				}

				bodyVOs[j] = bodyVO;
			}
			//组装AggVO
			aggVO.setParentVO(headVO);
			if(aggVO instanceof BXVO){
				((nc.vo.ep.bx.BXVO)aggVO).setcShareDetailVo((CShareDetailVO[])bodyVOs);
			}else{
				aggVO.setChildrenVO(bodyVOs);	
			}
		} catch (Exception e) {
			throw new Exception("json参数转换AggVO出错 ！"+ e.getMessage());
		}

		return aggVO;
	}
	/**
	 * 内转单VO设值
	 * @param voClass
	 * @param vo
	 * @param jaonObject
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 */
	@SuppressWarnings({ "unchecked"})
	protected static void setRecValue(Class<? extends CircularlyAccessibleValueObject> voClass,CircularlyAccessibleValueObject vo, JSONObject jaonObject) throws InstantiationException, IllegalAccessException {
		CircularlyAccessibleValueObject recvo;
		recvo=voClass.newInstance();				
		nc.vo.pubapp.pattern.model.meta.entity.vo.ModelVOMeta model =
				(nc.vo.pubapp.pattern.model.meta.entity.vo.ModelVOMeta)((SuperVO)recvo).getMetaData();
		IAttributeMeta[] iMeta = model.getAttributes();
		Iterator<String> it;
		String attributeName;
		Object value;
		it = (Iterator<String>) jaonObject.keys();
		while (it.hasNext()) {
			attributeName = it.next();
			if (MMValueCheck.isEmpty(attributeName)) {
				continue;
			}
			value = jaonObject.get(attributeName);
			if (value == null || MMValueCheck.isEmpty(value.toString())) {
				continue;
			}
			for (int j = 0; j < iMeta.length; j++) {										
				Attribute field=(Attribute)iMeta[j];
				String  attriname=field.getName();
				nc.vo.pub.JavaType type=field.getJavaType();												
				if (attributeName.equalsIgnoreCase(attriname.trim())) {			
					if (type.name().equals("String")) {
						vo.setAttributeValue(attributeName, value);
					} else if (type.name().equals("Integer")) {
						vo.setAttributeValue(attributeName,
								Integer.parseInt(value.toString()));
					} else if (type.name().equals("UFDouble")) {
						vo.setAttributeValue(attributeName, new UFDouble(
								value.toString()));
					} else if (type.name().equals("UFBoolean")) {
						vo.setAttributeValue(attributeName, new UFBoolean(
								value.toString()));
					} else if (type.name().equals("UFDate")) {
						vo.setAttributeValue(attributeName, new UFDate(
								value.toString()));
					} else if (type.name().equals("UFDateTime")) {
						vo.setAttributeValue(attributeName, new UFDateTime(
								value.toString()));
					} else {
						vo.setAttributeValue(attributeName, value);
					}
					break;
				}
			}
		}
		//VO状态
		vo.setStatus(VOStatus.NEW);
	}
	/**
	 * VO设值
	 * @param voClass
	 * @param vo
	 * @param jaonObject
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	protected static void setValue(Class<? extends CircularlyAccessibleValueObject> voClass,CircularlyAccessibleValueObject vo, JSONObject jaonObject) {
		Field[] headFields = voClass.getFields();
		Iterator<String> it;
		String attributeName;
		Object value;
		it = (Iterator<String>) jaonObject.keys();
		while (it.hasNext()) {
			attributeName = it.next();
			if (MMValueCheck.isEmpty(attributeName)) {
				continue;
			}
			value = jaonObject.get(attributeName);
			if (value == null || MMValueCheck.isEmpty(value.toString())) {
				continue;
			}
			if ("bbje".equalsIgnoreCase(attributeName)|| "assume_amount".equalsIgnoreCase(attributeName)) {
				vo.setAttributeValue(attributeName,new UFDouble(value.toString()));
			}else if ("rowno".equalsIgnoreCase(attributeName)) {
				vo.setAttributeValue(attributeName,Integer.parseInt(value.toString()));
			}
			else {
				for (int j = 0; j < headFields.length; j++) {
					Field field = headFields[j];
					if (headFields[j].getName().equalsIgnoreCase(attributeName)) {
						Class type = field.getType();
						if (type == String.class) {
							vo.setAttributeValue(attributeName, value);
						} else if (type == Integer.class) {
							vo.setAttributeValue(attributeName,
									Integer.parseInt(value.toString()));
						} else if (type == UFDouble.class) {
							vo.setAttributeValue(attributeName, new UFDouble(
									value.toString()));
						} else if (type == UFBoolean.class) {
							vo.setAttributeValue(attributeName, new UFBoolean(
									value.toString()));
						} else if (type == UFDate.class) {
							vo.setAttributeValue(attributeName, new UFDate(
									value.toString()));
						} else if (type == UFDateTime.class) {							
							vo.setAttributeValue(attributeName, new UFDateTime(
									value.toString()));															
						} else {
							vo.setAttributeValue(attributeName, value);
						}
						break;
					}
				}
			}
		}
		//VO状态
		vo.setStatus(VOStatus.NEW);
	}
	
	/**
	 * 非空校验+执行公式
	 * @param hConfigCode
	 * 				表头公式配置编码
	 * @param bConfigCode
	 * 				表体公式配置编码
	 * @param headVO
	 * 				表头VO
	 * @param bodyVOs
	 * 				表体VO
	 * @throws BusinessException
	 */
	public static void notNullCheckAndExFormula(String hConfigCode,String bConfigCode,AggregatedValueObject aggVO) throws Exception {
		HashMap<String,ArrayList<String>> hFormulaone = getFormulas(hConfigCode,SapConstants.DIRECTION_SAP2NC);
		HashMap<String,ArrayList<String>> bFormulaone = getFormulas(bConfigCode,SapConstants.DIRECTION_SAP2NC);
		List<String> headKeys = hFormulaone.get(SapConstants.NOTNULL_FIELD_KEY);
		List<String> headKeYsName = hFormulaone.get(SapConstants.NC_FIELD_NAME);
		List<String> bodyKeys = new ArrayList<String>();
		List<String> bodyKeysName = new ArrayList<String>();
		if(bFormulaone!=null){
			bodyKeys=bFormulaone.get(SapConstants.NOTNULL_FIELD_KEY);	
			 bodyKeysName=bFormulaone.get(SapConstants.NC_FIELD_NAME);	
		}
		
		
		ArrayList<String> hFormula = hFormulaone.get(SapConstants.FORMULA_KEY);
		ArrayList<String> bFormula = new ArrayList<String>(); 
		if(bFormulaone!=null){
			bFormula =bFormulaone.get(SapConstants.FORMULA_KEY);
		}
		ExtFormulaParser extFormulaParser = new ExtFormulaParser();
//		if(aggVO instanceof BXVO){//报销单
//			
//			BXVO bxvo=(BXVO)aggVO;
//			// 费用分摊单信息有误但NC没有返回报错给sap  begin
//			CShareDetailVO[] shareVO=bxvo.getcShareDetailVo();
//			if(shareVO!=null&&shareVO.length>0){
//				notNullCheck(headKeys,headKeYsName,bodyKeysName,bodyKeys, aggVO.getParentVO(), bxvo.getcShareDetailVo(),1);	
//				extFormulaParser.execFormulas(hFormula.toArray(new String[0]), bFormula.toArray(new String[0]), bxvo, null);
//				notNullCheck(headKeys,headKeYsName,bodyKeysName,bodyKeys, aggVO.getParentVO(),bxvo.getcShareDetailVo(),2);
//			}else {
//				notNullCheck(headKeys,headKeYsName,bodyKeysName,bodyKeys, aggVO.getParentVO(), aggVO.getChildrenVO(),1);	
//				extFormulaParser.execFormulas(hFormula.toArray(new String[0]), bFormula.toArray(new String[0]), bxvo, null);
//				notNullCheck(headKeys,headKeYsName,bodyKeysName,bodyKeys, aggVO.getParentVO(),aggVO.getChildrenVO(),2);
//			}
//			//费用分摊单信息有误但NC没有返回报错给sap end
//			
//		}else 
			notNullCheck(headKeys,headKeYsName,bodyKeysName,bodyKeys, aggVO.getParentVO(), aggVO.getChildrenVO(),1);
			extFormulaParser.execFormulas(hFormula.toArray(new String[0]), bFormula.toArray(new String[0]),aggVO);
			notNullCheck(headKeys,headKeYsName,bodyKeysName,bodyKeys, aggVO.getParentVO(),aggVO.getChildrenVO(),2);
	
	}
	
	/**
	 * 非空字段校验
	 * @param headKeys
	 * 			表头字段
	 * @param bodyKeys
	 * 			表体字段
	 * @param bodyKeys2 
	 * @param bodyKeysName 
	 * @param headVO
	 * 			表头VO
	 * @param bodyVOs
	 * 			表体VO
	 * @param type
	 * 			1：第一次非空校验，2：转换后非空校验
	 * @throws Exception
	 */
	public static void notNullCheck(List<String> headKeys,List<String> headKeYsName,List<String> bodyKeysName, List<String> bodyKeys, CircularlyAccessibleValueObject headVO,CircularlyAccessibleValueObject[] bodyVOs,int type) throws Exception{
		Set<String> keySetName = new HashSet<String>();
		Object value;
		if(CollectionUtils.isNotEmpty(headKeys) && headVO!=null){
			for (int i = 0; i < headKeys.size(); i++) {
				String key=headKeys.get(i);
				value = headVO.getAttributeValue(key);
				if(MMValueCheck.isEmpty(value)){
					keySetName.add(headKeYsName.get(i));
				}
			}
		}
		if(CollectionUtils.isNotEmpty(bodyKeys) && MMValueCheck.isNotEmpty(bodyVOs)){
		     for (int i = 0; i < bodyKeys.size(); i++) {
				for(CircularlyAccessibleValueObject bodyVO:bodyVOs){
					String key=bodyKeys.get(i);
					value = bodyVO.getAttributeValue(key);
					if(MMValueCheck.isEmpty(value)){
						keySetName.add(bodyKeysName.get(i));
					}
				}
			}
		}
		if(keySetName.size()>0){
			String keyName = StringUtils.join(keySetName.toArray(), "、");
			if(type==1){
				throw new BusinessException( "以下字段不能为空："+keyName);	
			}else{
				throw new BusinessException( "以下字段转换失败："+keyName);	
			}
		}
	}
	/**
	 * 查询公式
	 * @param code			表头编码
	 * @param direction		方向【SAP->NC ? NC->SAP】
	 * @return
	 * @throws BusinessException
	 */
	public static HashMap<String,ArrayList<String>> getFormulas(String code,int direction) throws BusinessException{
			StringBuffer sqlstr = new StringBuffer("");
			sqlstr.append("item = (select pk_head").append("\r\n");
			sqlstr.append("  from sap_syproconfig").append("\r\n");
			sqlstr.append(" where billno = '");
			sqlstr.append(code);
			sqlstr.append("'").append("\r\n");
			sqlstr.append("   and nvl(dr, 0) = 0) and nvl(dr, 0) = 0  and isenable_sn='Y' "); 
			List<SyProConfigBVO> syProConfigBVOs = (List<SyProConfigBVO>)getQueryBS().retrieveByClause(SyProConfigBVO.class, sqlstr.toString());
			if(syProConfigBVOs!=null && syProConfigBVOs.size()>0){
			HashMap<String,ArrayList<String>> formulasMap = new HashMap<String,ArrayList<String>>();
			//非空字段
			ArrayList<String> notNullField = new ArrayList<String>();
			//SAP->NC ？ NC->SAP 公式
			ArrayList<String> formula = new ArrayList<String>();
			//NC字段编码
			ArrayList<String> nc_field_code = new ArrayList<String>();
			//NC字段名称
			ArrayList<String> nc_field_name = new ArrayList<String>();
			//SAP字段编码
			ArrayList<String> sap_field_code = new ArrayList<String>();
			Collections.sort(syProConfigBVOs, new SapVOSort(direction));
			for(SyProConfigBVO syProConfigBVO:syProConfigBVOs){
				if(SapConstants.DIRECTION_SAP2NC==direction){
					//SAP->NC
					if(syProConfigBVO.getIsenable_sn().booleanValue()){
						if(!syProConfigBVO.getNullflag().booleanValue()){
							notNullField.add(syProConfigBVO.getField_code());
							nc_field_name.add(syProConfigBVO.getField_name());
						}
						formula.add(syProConfigBVO.getFormula_sn());
					}
					//把NC编码也放进去 begin
					nc_field_code.add(syProConfigBVO.getField_code());
					//把NC编码也放进去 end
				}else if(SapConstants.DIRECTION_NC2SAP==direction){
					//NC->SAP
					if(syProConfigBVO.getIsenable_ns().booleanValue()){
						formula.add(syProConfigBVO.getFormula_ns());
						nc_field_code.add(syProConfigBVO.getField_code());
						sap_field_code.add(syProConfigBVO.getField_code_sap());
					}
				}
			}
			formulasMap.put(SapConstants.NOTNULL_FIELD_KEY, notNullField);
			formulasMap.put(SapConstants.FORMULA_KEY, formula);
			formulasMap.put(SapConstants.NC_FIELD_CODE, nc_field_code);
			formulasMap.put(SapConstants.SAP_FIELD_CODE, sap_field_code);
			formulasMap.put(SapConstants.NC_FIELD_NAME, nc_field_name);
			return formulasMap;
		}
		return null;
	}
}
