package nc.bs.uap.wgpt.process;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.alibaba.fastjson.JSON;

import nc.bs.arap.bill.ArapBillPubUtil;
import nc.bs.arap.util.BillMoneyVUtils;
import nc.bs.dao.BaseDAO;
import nc.bs.framework.common.InvocationInfoProxy;
import nc.bs.framework.common.NCLocator;
import nc.itf.arap.fieldmap.IBillFieldGet;
import nc.itf.fi.pub.Currency;
import nc.net.servlet.IReturnStatus;
import nc.pub.sap.constant.SapConstants;
import nc.pubitf.accperiod.AccountCalendar;
import nc.pubitf.arap.bill.IArapBillPubService;
import nc.pubitf.arap.pay.IArapPayBillPubQueryService;
import nc.util.mmf.framework.base.MMArrayUtil;
import nc.util.mmf.framework.base.MMValueCheck;
import nc.util.uap.wgpt.WuYeWgptUtil;
import nc.vo.arap.basebill.BaseAggVO;
import nc.vo.arap.basebill.BaseBillVO;
import nc.vo.arap.basebill.BaseItemVO;
import nc.vo.arap.global.ArapBillVOConsts;
import nc.vo.arap.pay.AggPayBillVO;
import nc.vo.arap.pub.BillEnumCollection;
import nc.vo.arap.pub.BillEnumCollection.BillSatus;
import nc.vo.arap.pub.BillEnumCollection.FromSystem;
import nc.vo.arap.pub.BillEnumCollection.InureSign;
import nc.vo.bd.period.AccperiodVO;
import nc.vo.bd.period2.AccperiodmonthVO;
import nc.vo.esb.ResultEsbVO;
import nc.vo.esb.ResultVO;
import nc.vo.fipub.exception.ExceptionHandler;
import nc.vo.jcom.lang.StringUtil;
import nc.vo.pub.BusinessException;
import nc.vo.pub.CircularlyAccessibleValueObject;
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.data.ValueUtils;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nc.vo.tmpub.util.ArrayUtil;
import nc.vo.tmpub.util.MathUtil;
import nc.vo.wgpt.log.WuYeWgptLogVO;
import ncc.pub.wywgpt.utils.WyWGPTUtils;
import uap.json.JSONArray;
import uap.json.JSONObject;
/**
 * @author 符耀铭
 * @date 2020年10月14日
 * @description 二开新建的类,碧彩京东接口改造，碧彩商城同步红字付款单
 */
public class WritePaybillRedInfoProcess {

	public String writePaybillRed(JSONObject jsonobj) {
		String rsdata = null;
		String nc_id = null;
		Object billno = null;
		ResultEsbVO<ResultVO> esb = new ResultEsbVO<ResultVO>();
		ResultVO result = new ResultVO();
		result.setResult("");
		esb.setResultInfo(result);
		try {
			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 {
				JSONObject requestInfo=jsonobj.getJSONObject("requestInfo");
				JSONObject headerJson =requestInfo.getJSONObject("Header");
				JSONArray bodyJsonArray=requestInfo.getJSONArray("Items");
				
				String wgptNo=headerJson.getString("def47");//碧彩商城订单号
				
				IArapPayBillPubQueryService queryService=NCLocator.getInstance().lookup(IArapPayBillPubQueryService.class);
				String whereString = " pk_paybill in (select pk_paybill from ap_payitem fb where fb.dr=0 and  fb.top_billid in (select  pk_order from po_order where nvl(dr,0)=0 and vdef15='"+wgptNo+"'))  and nvl(dr,0)=0  order by (case  when  money > 0  then  1  else  0  end) desc";
				AggPayBillVO[] aggPayBillVOs=queryService.queryVOsByWhere(whereString);

				if(MMArrayUtil.isEmpty(aggPayBillVOs)) {
					result.setCode(IReturnStatus.FAILING);//失败
					result.setMessage("传递红字付款单失败！在NC系统不存在碧彩订单号：【"+wgptNo+"】生成的付款单。");
					WuYeWgptUtil.createResultEsbVO(esb);// 初始化响应对象
					esb.getEsbInfo().setReturnCode(IReturnStatus.ESB_FAILING_CODE);
					esb.getEsbInfo().setReturnStatus(IReturnStatus.ESB_FAILING);
					esb.getEsbInfo().setReturnMsg("失败");
					esb.setResultInfo(result);// 设置响应内容
				}else {
					HashMap<String, ArrayList<String>> headConfigMap = WyWGPTUtils.getFormulas("WY_BCSC_PAYBILLRED_HEAD", SapConstants.DIRECTION_SAP2NC);
					HashMap<String, ArrayList<String>> itemConfigMap = WyWGPTUtils.getFormulas("WY_BCSC_PAYBILLRED_BODY", SapConstants.DIRECTION_SAP2NC);
					
					setValue(aggPayBillVOs[0].getHeadVO(), headerJson);

					setValue(aggPayBillVOs[0].getChildrenVO()[0],bodyJsonArray.getJSONObject(0));
					
					// 转换前非空校验、执行公式、翻译后各项非空校验
					WyWGPTUtils.notNullCheckAndExFormula("WY_BCSC_PAYBILLRED_HEAD", "WY_BCSC_PAYBILLRED_BODY", aggPayBillVOs[0]);
					
					BaseAggVO writeBackBill = initRedBillVO(aggPayBillVOs[0]);
					writeBackBill.getHeadVO().setTransientFlag(ArapBillVOConsts.ACT_COPY_BILL);
					
					List<BaseAggVO> vos=new ArrayList<BaseAggVO>();
					
					vos.add(writeBackBill);
					
					ArrayUtil.addArrayToList(vos, aggPayBillVOs);
					
					checkAmount(vos.toArray(new BaseAggVO[0]));
					// 设置红冲标志
					((BaseBillVO) aggPayBillVOs[0].getParentVO()).setIsreded(UFBoolean.TRUE);
					// 保存生成的红冲单据
					IArapBillPubService service = NCLocator.getInstance().lookup(IArapBillPubService.class);
					ArrayList<String> headNCCodeList=headConfigMap.get(SapConstants.NC_FIELD_CODE);
					ArrayList<String> bodyNCCodeList=itemConfigMap.get(SapConstants.NC_FIELD_CODE);
					
//					((BaseItemVO[]) writeBackBill.getChildrenVO())[0].setSrc_billid(aggPayBillVOs[0].getBodyVOs()[0].getSrc_billid());
//					((BaseItemVO[]) writeBackBill.getChildrenVO())[0].setSrc_billtype(aggPayBillVOs[0].getBodyVOs()[0].getSrc_billtype());
//					((BaseItemVO[]) writeBackBill.getChildrenVO())[0].setSrc_itemid(aggPayBillVOs[0].getBodyVOs()[0].getSrc_itemid());
//					((BaseItemVO[]) writeBackBill.getChildrenVO())[0].setSrc_tradetype(aggPayBillVOs[0].getBodyVOs()[0].getSrc_tradetype());
//					((BaseItemVO[]) writeBackBill.getChildrenVO())[0].setTop_billid(aggPayBillVOs[0].getBodyVOs()[0].getTop_billid());
//					((BaseItemVO[]) writeBackBill.getChildrenVO())[0].setTop_billtype(aggPayBillVOs[0].getBodyVOs()[0].getTop_billtype());
//					((BaseItemVO[]) writeBackBill.getChildrenVO())[0].setTop_tradetype(aggPayBillVOs[0].getBodyVOs()[0].getTop_tradetype());
					
					writeBackBill=service.save(writeBackBill);
					nc_id=writeBackBill.getPrimaryKey();
					billno=writeBackBill.getHeadVO().getBillno();
					new BaseDAO().updateVO((SuperVO) aggPayBillVOs[0].getParentVO(), new String[] { "isreded" });
					result.setCode(IReturnStatus.SUCCEED);// 成功
					result.setMessage("同步红冲付款单成功");
					com.alibaba.fastjson.JSONObject redbillObject=new com.alibaba.fastjson.JSONObject();
					redbillObject.put("billno", billno);
					result.setResult(redbillObject);
					WuYeWgptUtil.createResultEsbVO(esb);
					esb.setResultInfo(result);
				}

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

			WuYeWgptLogVO logVO = new WuYeWgptLogVO();
			logVO.setNc_id(nc_id);
			logVO.setOther_id(nc_id + "");
			logVO.setBillno(billno+"");
			logVO.setTranstypecode("FK");
			logVO.setItfcode("WGPT-NC-005");
			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 void setValue(CircularlyAccessibleValueObject vo, JSONObject jaonObject) throws Exception{
		Map<String,String> fieldTypeMap = new HashMap<String,String>();
		String[] arr;
		Method[]  methods=vo.getClass().getMethods();
		List<Field> dataTypes=Arrays.asList(vo.getClass().getFields());

		for(Method m:methods){
			fieldTypeMap.put(m.getName().toLowerCase(), m.getReturnType().getSimpleName());
		}
		for(Field dataType:dataTypes){
			//			arr = dataType.split(",");
			fieldTypeMap.put(dataType.getName(), dataType.getType().getSimpleName());
		}
		String attributeName;
		String type;
		Object value;
		Iterator<String> it = (Iterator<String>) jaonObject.keys();
		while (it.hasNext()) {
			attributeName = it.next();
			if (StringUtil.isEmptyWithTrim(attributeName)) {
				continue;
			}
			value = jaonObject.get(attributeName);
			if (value == null || StringUtil.isEmptyWithTrim(value.toString())) {
				continue;
			}
			type = fieldTypeMap.get(attributeName.toLowerCase());
			if(type==null){
				type=fieldTypeMap.get("get"+attributeName.toLowerCase());
			}
			if(type==null){
				vo.setAttributeValue(attributeName, value);
			}else if ("Integer".equals(type)) {
				value=jaonObject.optInt(attributeName);
				for(int m=0;m<methods.length;m++){
					if(methods[m].getName().toLowerCase().equals("set"+attributeName)){
						vo.getClass().getMethod(methods[m].getName(),methods[m].getParameterTypes()[0]).invoke(vo, new Object[]{Integer.parseInt(value.toString())});
						break;
					}
				}
			} else if ("UFDouble".equals(type)) {
				vo.setAttributeValue(attributeName, new UFDouble(jaonObject.optDouble(attributeName)));
			} else if ("UFBoolean".equals(type)) {
				vo.setAttributeValue(attributeName, new UFBoolean(value.toString()));
			} else if ("UFDate".equals(type)) {
				vo.setAttributeValue(attributeName, new UFDate(value.toString()));
			} else if ("UFDateTime".equals(type)) {
				SimpleDateFormat sdfs = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				String notdate = sdfs.format(ValueUtils.getUFLiteralDate(value).getMillis());
				vo.setAttributeValue(attributeName, new UFDateTime(notdate));
			} else {
				vo.setAttributeValue(attributeName,value);
				if(null==vo.getAttributeValue(attributeName)){
					for(int m=0;m<methods.length;m++){
						if(methods[m].getName().toLowerCase().equals("set"+attributeName)){
							vo.getClass().getMethod(methods[m].getName(),methods[m].getParameterTypes()[0]).invoke(vo, new Object[]{value});
							break;
						}
					}

				}
			}
		}
		//VO状态
		vo.setStatus(VOStatus.NEW);
	}
	public void checkAmount(BaseAggVO[] aggPayBillVOs) throws BusinessException{
		if(MMValueCheck.isEmpty(aggPayBillVOs)) {
			return;
		}
		UFDouble sumDouble=UFDouble.ZERO_DBL;
		Set<String> repeatSet=new HashSet<String>();
		for(int i=0;i<aggPayBillVOs.length;i++) {
			//碧彩商城退款单唯一标识
			Object def40 =aggPayBillVOs[i].getHeadVO().getAttributeValue("def40");
			if(null!=def40) {
				if(repeatSet.contains(def40) && aggPayBillVOs[i].getHeadVO().getMoney().doubleValue()<0) {
					ExceptionUtils.wrappBusinessException("NC已存在退款单【"+def40+"】，请不要重复传递！");
				}else {
					repeatSet.add(def40+"");
				}
			}
			sumDouble=MathUtil.add(sumDouble, aggPayBillVOs[i].getHeadVO().getMoney());
		}
		if(sumDouble.doubleValue()<0) {
			ExceptionUtils.wrappBusinessException("红冲付款单金额大于预付款单金额，生成红冲付款单失败！");
		}
	}
	
	public <T extends BaseAggVO> BaseAggVO initRedBillVO(T bill) throws BusinessException{
		String[] itemQuantityKeys = new String[] { IBillFieldGet.QUANTITY_DE, IBillFieldGet.QUANTITY_CR, IBillFieldGet.QUANTITY_BAL };
		String[] itemMnyKeys = new String[] { IBillFieldGet.MONEY_DE, IBillFieldGet.LOCAL_MONEY_DE, IBillFieldGet.LOCAL_MONEY_CR, IBillFieldGet.MONEY_CR, IBillFieldGet.MONEY_BAL, IBillFieldGet.LOCAL_MONEY_BAL,
				IBillFieldGet.LOCAL_TAX_DE, IBillFieldGet.NOTAX_DE, IBillFieldGet.LOCAL_NOTAX_DE, IBillFieldGet.LOCAL_TAX_CR, IBillFieldGet.NOTAX_CR, IBillFieldGet.LOCAL_NOTAX_CR, IBillFieldGet.GROUPBALANCE,
				IBillFieldGet.GLOBALBALANCE, IBillFieldGet.GROUPDEBIT, IBillFieldGet.GLOBALDEBIT, IBillFieldGet.GROUPTAX_DE, IBillFieldGet.GLOBALTAX_DE, IBillFieldGet.GROUPNOTAX_DE, IBillFieldGet.GLOBALNOTAX_DE, IBillFieldGet.GROUPCREBIT,
				IBillFieldGet.GLOBALCREBIT, IBillFieldGet.GROUPTAX_CRE, IBillFieldGet.GLOBALTAX_CRE, IBillFieldGet.GROUPNOTAX_CRE, IBillFieldGet.GLOBALNOTAX_CRE, IBillFieldGet.OCCUPATIONMNY
				,IBillFieldGet.CALTAXMNY,IBillFieldGet.NOSUBTAX};
		String[] clearItemKeys = new String[] { IBillFieldGet.PAYDATE, IBillFieldGet.PAYMAN, IBillFieldGet.PAYFLAG, IBillFieldGet.BILLNO, IBillFieldGet.OCCUPATIONMNY ,"ts"};
		// 票据号也不能带到红字单上
		String[] clearHeadKeys = new String[] { IBillFieldGet.SETTLENUM, IBillFieldGet.PAYDATE, IBillFieldGet.PAYMAN, IBillFieldGet.SETTLEFLAG, IBillFieldGet.BILLNO, IBillFieldGet.APPROVESTATUS, IBillFieldGet.ISFLOWBILL, IBillFieldGet.ISFROMINDEPENDENT};
		T vo = (T) bill.clone();
		BaseBillVO parent = (BaseBillVO) vo.getParentVO();
		String billno = parent.getBillno();
		String pk_bill = parent.getPrimaryKey();
		BaseItemVO[] children = (BaseItemVO[]) vo.getChildrenVO();

		UFDouble NEGATIVE = new UFDouble("-1");
		UFDouble ZERO = new UFDouble("0");
		InvocationInfoProxy info = InvocationInfoProxy.getInstance();
		UFDate current =new UFDate(info.getBizDateTime());
		String userid = info.getUserId();
		// 注释?
		AccountCalendar calendar = AccountCalendar.getInstanceByPk_org(parent.getPk_org());
		calendar.setDate(current);
		AccperiodVO accperiod = calendar.getYearVO();
		accperiod.setAccperiodmonth(new AccperiodmonthVO[] { calendar.getMonthVO() });

		String periodYear = accperiod.getPeriodyear();
		String periodMonth = accperiod.getAccperiodmonth()[0].getAccperiodmth();

		// 清空表头项
		for (String key : clearHeadKeys) {
			parent.setAttributeValue(key, null);
		}
		
		for (int i = 0; i < children.length; i++) {
			if(parent.getSrc_syscode()!=null && (parent.getSrc_syscode().equals(FromSystem.AM.VALUE) || parent.getSrc_syscode().equals(FromSystem.CT.VALUE))){
				children[i].setSrc_billid(null);
				children[i].setSrc_billtype(null);
				children[i].setSrc_itemid(null);
				children[i].setSrc_tradetype(null);
			}
		}
		
		parent.setBillmaker(userid);
		parent.setTransientFlag(ArapBillVOConsts.ACT_RED_BILL);
		parent.setPrimaryKey(null);
		parent.setApprover(InvocationInfoProxy.getInstance().getUserId());
		long bizDateTime = InvocationInfoProxy.getInstance().getBizDateTime();
		parent.setApprovedate(new UFDateTime(bizDateTime));
		parent.setBilldate(current);
		parent.setBusidate(current);
		parent.setSignyear(periodYear);
		parent.setSignperiod(periodMonth);
		parent.setSigndate(current);
		parent.setSignuser(userid);
		parent.setApprovestatus(BillEnumCollection.ApproveStatus.COMMIT.VALUE.intValue());

		parent.setIsmandatepay(UFBoolean.FALSE);
		parent.setSettletype(ArapBillVOConsts.m_intJSZXZF_NONE);
		parent.setEffectstatus(ArapBillVOConsts.m_intSXBZ_VALID);
		parent.setSrc_syscode(parent.getSyscode());
		parent.setIsreded(ArapBillVOConsts.RED);
		parent.setTs(null);

		parent.setGlobalrate(parent.getGlobalrate() == null ? UFDouble.ZERO_DBL : parent.getGlobalrate());
		parent.setGrouprate(parent.getGrouprate() == null ? UFDouble.ZERO_DBL : parent.getGrouprate());

		for (int i = 0; i < children.length; i++) {
			children[i].setBankrelated_code(null);
			children[i].setTop_itemid(children[i].getTop_itemid());
			children[i].setTop_billid(children[i].getTop_billid());
			children[i].setTop_billtype(children[i].getTop_billtype());
			children[i].setTop_tradetype(children[i].getTop_tradetype());
			children[i].setParentPK(null);
			children[i].setPrimaryKey(null);
			children[i].setBusidate(current);
			children[i].setBilldate(current);
			children[i].setIsverifyfinished(UFBoolean.FALSE);
			children[i].setStatus(VOStatus.NEW);
			children[i].setConfernum(null);
			//红冲需要清空的字段
			children[i].setSettlemoney(children[i].getOccupationmny());
			children[i].setSettlecurr(children[i].getPk_currtype());
			for (String key : clearItemKeys) {
				children[i].setAttributeValue(key, null);
			}

			for (String key : itemQuantityKeys) {
				UFDouble value = (UFDouble) children[i].getAttributeValue(key);
				if (null != value && !value.equals(ZERO)) {
					children[i].setAttributeValue(key, value.multiply(NEGATIVE));
				}
			}

			for (String key : itemMnyKeys) {
				UFDouble value = (UFDouble) children[i].getAttributeValue(key);
				if (null != value && !value.equals(ZERO)) {
					children[i].setAttributeValue(key, value.multiply(NEGATIVE));
				}
			}

			UFDouble balmoney = null;
			UFDouble orgmoney = null;
			UFDouble groupmoney = null;
			UFDouble globalmoney = null;

			UFDouble moneyCr = children[i].getSettlemoney().multiply(NEGATIVE);
			UFDouble moneyCrOrg = children[i].getLocal_money_de();
			UFDouble moneyCrGroup = children[i].getGroupdebit();
			UFDouble moneyCrGlobal = children[i].getGlobaldebit();
			balmoney = null == moneyCr ? UFDouble.ZERO_DBL : moneyCr;
			orgmoney = null == moneyCrOrg ? UFDouble.ZERO_DBL : moneyCrOrg;
			groupmoney = null == moneyCrGroup ? UFDouble.ZERO_DBL : moneyCrGroup;
			globalmoney = null == moneyCrGlobal ? UFDouble.ZERO_DBL : moneyCrGlobal;

			children[i].setMoney_bal(balmoney);
			children[i].setOccupationmny(balmoney);
			children[i].setLocal_money_bal(orgmoney);
			children[i].setGroupbalance(groupmoney);
			children[i].setGlobalbalance(globalmoney);

			UFDouble realQuantityde = null == children[i].getQuantity_de() ? UFDouble.ZERO_DBL : children[i].getQuantity_de();
			UFDouble realQuantitycr = null == children[i].getQuantity_cr() ? UFDouble.ZERO_DBL : children[i].getQuantity_cr();
			children[i].setQuantity_bal(realQuantitycr.add(realQuantityde));

			children[i].setGlobalrate(children[i].getGlobalrate() == null ? UFDouble.ZERO_DBL : children[i].getGlobalrate());
			children[i].setGrouprate(children[i].getGrouprate() == null ? UFDouble.ZERO_DBL : children[i].getGrouprate());
			children[i].setScomment(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006pub_0", "02006pub-0463")/*
			 * @res
			 * "红冲原单据号:"
			 */+ billno);
		}
		
		try {
			boolean reset=false;
			for(int i = 0; i < children.length; i++){
				if(Currency.getLocalCurrPK(children[i].getPk_org())!= children[i].getPk_currtype()){
					children[i].setRate(null);
					reset=true;
				}
				if(!children[i].getMoney_bal().equals(children[i].getMoney_cr().add(children[i].getMoney_de())) && children[i].getMoney_bal().compareTo(UFDouble.ZERO_DBL)!=0){
					if (children[i].getDirection().equals(BillEnumCollection.Direction.CREDIT.VALUE)) {
						children[i].setMoney_cr(children[i].getMoney_bal());
					} else if (children[i].getDirection().equals(BillEnumCollection.Direction.DEBIT.VALUE)) {
						children[i].setMoney_de(children[i].getMoney_bal().abs().multiply(NEGATIVE));
					}
					reset=true;
				}
			}
			if(reset){
				ArapBillPubUtil.processMoney(vo);
			}
		} catch (BusinessException e) {
			ExceptionHandler.handleRuntimeException(e);
		}
		
		BillMoneyVUtils.sumBodyToHead(parent, children);
		// 状态
		vo.getHeadVO().setBillstatus(BillSatus.Save.VALUE);
		vo.getHeadVO().setEffectstatus(InureSign.NOINURE.VALUE);

		return vo;
	}
}
