package nc.bs.pu.wgpt.process;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import nc.bcmanage.bs.IBusiCenterManageService;
import nc.bs.dao.BaseDAO;
import nc.bs.framework.common.InvocationInfoProxy;
import nc.bs.framework.common.NCLocator;
import nc.bs.framework.comn.NetStreamContext;
import nc.bs.framework.server.ISecurityTokenCallback;
import nc.itf.pubapp.pub.smart.IBillQueryService;
import nc.itf.uap.pf.IPFWorkflowQry;
import nc.jdbc.framework.processor.ColumnListProcessor;
import nc.net.servlet.IReturnStatus;
import nc.net.servlet.SapToNcEsbJsonServlet;
import nc.pub.sap.constant.SapConstants;
import nc.pubitf.para.SysInitQuery;
import nc.pubitf.pu.m4201.IStockFinanceSettleInfoQuery;
import nc.util.uap.wgpt.WuYeWgptUtil;
import nc.vo.esb.ResultEsbVO;
import nc.vo.esb.ResultVO;
import nc.vo.ic.general.define.MetaNameConst;
import nc.vo.ic.m45.entity.PurchaseInBodyVO;
import nc.vo.ic.m45.entity.PurchaseInVO;
import nc.vo.ic.pub.util.CollectionUtils;
import nc.vo.ic.pub.util.NCBaseTypeUtils;
import nc.vo.ic.pub.util.StringUtil;
import nc.vo.ic.pub.util.VOEntityUtil;
import nc.vo.ic.pub.util.ValueCheckUtil;
import nc.vo.pu.m25.entity.InvoiceHeaderVO;
import nc.vo.pu.m25.entity.InvoiceItemVO;
import nc.vo.pu.m25.entity.InvoiceVO;
import nc.vo.pub.BusinessException;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nc.vo.pubapp.pattern.model.entity.bill.AbstractBill;
import nc.vo.tmpub.util.ArrayUtil;
import nc.vo.tmpub.util.SqlUtil;
import nc.vo.wgpt.log.WuYeWgptLogVO;
import ncc.bs.wy.tools.WyWGPTJsonTools;
import ncc.pub.wywgpt.utils.WyWGPTUtils;
import uap.json.JSONArray;
import uap.json.JSONObject;

/**
 * @Description: 【网购平台->NC】新增/修改采购发票
 * 
 * @author 邝鹏飞 【碧桂园-物业板块-网购平台接口】
 * @date 2021-5-26
 * @version with NCC2005
 */
public class WriteInvoiceInfoProcessForNC extends SapToNcEsbJsonServlet {

	@SuppressWarnings("unchecked")
	public String writeInvoiceInfo(JSONObject jsonobj) throws BusinessException {
		String rsdata = null;
		String nc_id = null;
		ResultVO result = new ResultVO();
		result.setResult("");
		Object deliveryNum = null;
		String vbdef12 = "";
		ResultEsbVO<ResultVO> esb = new ResultEsbVO<ResultVO>();
		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 = (JSONObject) jsonobj.get("requestInfo");
				JSONObject head = (JSONObject) requestInfo.get("Header");
				//deliveryNum = head.get("csourceid");
				Set<String> set = new HashSet<String>();
				deliveryNum = "";
				JSONArray items = new JSONArray(String.valueOf(requestInfo.get("Items")));
				for (int l = 0; l < items.length(); l++) {
					deliveryNum = deliveryNum+items.getJSONObject(l).getString("vbdef11")+",";
					set.add(items.getJSONObject(l).getString("vbdef11"));
					vbdef12 = vbdef12 + items.getJSONObject(l).getString("vbdef12")+",";
				}
				if (null != deliveryNum) {
					deliveryNum = deliveryNum.toString().substring(0, deliveryNum.toString().length()-1);
					InvoiceVO invoiceVO = WyWGPTJsonTools.jsonToOrderVO(jsonobj, InvoiceVO.class, InvoiceHeaderVO.class, InvoiceItemVO.class, null);
					// 转换前非空校验、执行公式、翻译后各项非空校验
					WyWGPTUtils.notNullCheckAndExFormula("WY25_HEAD_NC63", "WY25_BODY_NC63", invoiceVO);
					String sql = "select cgeneralhid from ic_purchasein_h where nvl(dr,0)=0 and " + SqlUtil.buildSqlForIn("vdef16", deliveryNum.toString().split(",")) + 
							" and " + SqlUtil.buildSqlForIn("freplenishflag", vbdef12.split(","));
					BaseDAO baseDAO = new BaseDAO();
					List<String> list = (List<String>) baseDAO.executeQuery(sql, new ColumnListProcessor());

					if (null != list && list.size() > 0) {
						IBillQueryService billQuery = NCLocator.getInstance().lookup(IBillQueryService.class);

						String qryInvoicSql = "select distinct pk_invoice from po_invoice_b where nvl(dr,0)=0 and "
								+ SqlUtil.buildSqlForIn("csourceid", list.toArray(new String[0]));

						List<String> pk_invoics = (List<String>) baseDAO.executeQuery(qryInvoicSql, new ColumnListProcessor());
						if (pk_invoics != null && pk_invoics.size() > 1) {
							throw new BusinessException("NC有" + pk_invoics.size() + "张发票");
						}
						if (pk_invoics != null && pk_invoics.size() > 0) {
							nc_id = pk_invoics.get(0);
							IPFWorkflowQry workflowQry = NCLocator.getInstance().lookup(IPFWorkflowQry.class);
							boolean isApproveFlowStartup = workflowQry.isApproveFlowStartup(pk_invoics.get(0), "25");
							if (isApproveFlowStartup) {
								result.setCode(IReturnStatus.FAILING);// 失败
								result.setMessage("发货单号：" + deliveryNum + "在NC系统对应的采购发票已进入审批流程，不允许修改！");
								WuYeWgptUtil.createResultEsbVO(esb);
								esb.getEsbInfo().setReturnStatus(IReturnStatus.ESB_FAILING);
								esb.getEsbInfo().setReturnMsg("失败");
								esb.setResultInfo(result);
							} else {
								InvoiceVO oldInvoiceVO = billQuery.querySingleBillByPk(InvoiceVO.class, pk_invoics.get(0));
								HashMap<String, ArrayList<String>> hFormulaone = WyWGPTUtils.getFormulas("WY25_HEAD_NC63", SapConstants.DIRECTION_SAP2NC);
								List<String> headKeys = hFormulaone.get(SapConstants.NC_FIELD_CODE);
								for (int j = 0; j < headKeys.size(); j++) {
									oldInvoiceVO.getParentVO().setAttributeValue(headKeys.get(j), invoiceVO.getParentVO().getAttributeValue(headKeys.get(j)));
								}
								
								HashMap<String, ArrayList<String>> bodyFormulaone = WyWGPTUtils.getFormulas("WY25_BODY_NC63", SapConstants.DIRECTION_SAP2NC);
								List<String> bodyKeys = bodyFormulaone.get(SapConstants.NC_FIELD_CODE);

								for(int a=0;a<oldInvoiceVO.getChildrenVO().length;a++){
									for(int b=0;b<invoiceVO.getChildrenVO().length;b++){
										if(oldInvoiceVO.getChildrenVO()[a].getVsourcerowno().equals(invoiceVO.getChildrenVO()[b].getVsourcerowno())
												&& oldInvoiceVO.getChildrenVO()[a].getVbdef11().equals(invoiceVO.getChildrenVO()[b].getVbdef11())){
											//exchangeVos[0].getChildrenVO()[a].setCproductorid(null);
											for(int h=0;h<bodyKeys.size();h++){
												oldInvoiceVO.getChildrenVO()[a].setAttributeValue(bodyKeys.get(h), invoiceVO.getChildrenVO()[b].getAttributeValue(bodyKeys.get(h)));
											}
											break;
										}
									}
								}
								
								WyWGPTUtils.getIPFBusiAction().processAction("SAVEBASE", oldInvoiceVO.getParentVO().getVtrantypecode(), null, oldInvoiceVO, null, null);
								result.setCode(IReturnStatus.SUCCEED);// 成功
								result.setMessage("修改采购发票成功");
								WuYeWgptUtil.createResultEsbVO(esb);
								esb.setResultInfo(result);
							}
						} else {
							AbstractBill[] abstractBills = billQuery.queryAbstractBillsByPks(PurchaseInVO.class, list.toArray(new String[0]));
							/**
							 * add by 符耀铭 2019-12-19 过滤掉已经结算的采购入库单的行  begin
							 */
							List<PurchaseInVO> queryInVOs=new ArrayList<PurchaseInVO>();
							
							for(int i=0;i<abstractBills.length;i++){
								queryInVOs.add((PurchaseInVO) abstractBills[i]);
							}
							
							PurchaseInVO[] filterVos =filterHasInvoicePurchaseIn(queryInVOs.toArray(new PurchaseInVO[0]));
							
							if(ArrayUtil.isNull(filterVos)){
								ExceptionUtils.wrappBusinessException("没有符合生成发票的行！");
							}
							
							/*
							 * int count = 0; for(PurchaseInVO pur:filterVos) { for(int
							 * i=0;i<pur.getChildrenVO().length;i++) { count++; } }
							 */
							if(queryInVOs.size() != set.size()) {
								ExceptionUtils.wrappBusinessException("没有关联到对应的全部采购入库单，请检查！");
							}
							//可能会生成多张发票
							InvoiceVO[] exchangeVos = (InvoiceVO[]) WuYeWgptUtil.getExchangeService().runChangeDataAry("45", "25", filterVos, null);
							/**
							 * add by 符耀铭 2019-12-19 过滤掉已经结算的采购入库单的行  end
							 */
							
							
							HashMap<String, ArrayList<String>> hFormulaone = WyWGPTUtils.getFormulas("WY25_HEAD_NC63", SapConstants.DIRECTION_SAP2NC);
							List<String> headKeys = hFormulaone.get(SapConstants.NC_FIELD_CODE);
							for (int j = 0; j < headKeys.size(); j++) {
								exchangeVos[0].getParentVO().setAttributeValue(headKeys.get(j), invoiceVO.getParentVO().getAttributeValue(headKeys.get(j)));
							}
							
							HashMap<String, ArrayList<String>> bodyFormulaone = WyWGPTUtils.getFormulas("WY25_BODY_NC63", SapConstants.DIRECTION_SAP2NC);
							List<String> bodyKeys = bodyFormulaone.get(SapConstants.NC_FIELD_CODE);

							for(int j=0;j<exchangeVos.length;j++) {
								for(int a=0;a<exchangeVos[j].getChildrenVO().length;a++){
									for(int b=0;b<invoiceVO.getChildrenVO().length;b++){
										if(exchangeVos[j].getChildrenVO()[a].getVsourcerowno()!=null &&
												invoiceVO.getChildrenVO()[b].getVsourcerowno()!=null &&
												exchangeVos[j].getChildrenVO()[a].getVbdef11()!=null &&
												invoiceVO.getChildrenVO()[b].getVbdef11()!=null) {
										if(exchangeVos[j].getChildrenVO()[a].getVsourcerowno().equals(invoiceVO.getChildrenVO()[b].getVsourcerowno())
												&& exchangeVos[j].getChildrenVO()[a].getVbdef11().equals(invoiceVO.getChildrenVO()[b].getVbdef11())){
											//exchangeVos[0].getChildrenVO()[a].setCproductorid(null);
											for(int h=0;h<bodyKeys.size();h++){
												if(!"crowno".equals(bodyKeys.get(h))) {
													exchangeVos[j].getChildrenVO()[a].setAttributeValue(bodyKeys.get(h), invoiceVO.getChildrenVO()[b].getAttributeValue(bodyKeys.get(h)));
												}
											}
											break;
										}
									 }
									}
								}
							}

							List<InvoiceItemVO> allItemVOs = new ArrayList<InvoiceItemVO>();
							for (int i = 0; i < exchangeVos.length; i++) {
								ArrayUtil.addArrayToList(allItemVOs, exchangeVos[i].getChildrenVO());
							}
							for (int row = 0; row < allItemVOs.size(); row++) {
								allItemVOs.get(row).setCrowno(String.valueOf((row + 1) * 10));
							}
							
							invoiceVO.setParentVO(exchangeVos[0].getParentVO());
							invoiceVO.setChildrenVO(allItemVOs.toArray(new InvoiceItemVO[0]));

							WyWGPTUtils.getIPFBusiAction().processAction("SAVEBASE", invoiceVO.getParentVO().getVtrantypecode(), null, invoiceVO, null, null);

							result.setCode(IReturnStatus.SUCCEED);// 成功
							result.setMessage("新增采购发票成功");
							WuYeWgptUtil.createResultEsbVO(esb);
							esb.setResultInfo(result);

							nc_id = invoiceVO.getParentVO().getPrimaryKey();
						}
					} else {
						result.setCode(IReturnStatus.FAILING);// 失败
						result.setMessage("根据发货单号：" + deliveryNum + "在NC系统找不到对应的采购入库单信息！");
						WuYeWgptUtil.createResultEsbVO(esb);
						esb.getEsbInfo().setReturnStatus(IReturnStatus.ESB_FAILING);
						esb.getEsbInfo().setReturnMsg("失败");
						esb.setResultInfo(result);
					}
				} else {
					result.setCode(IReturnStatus.FAILING);// 失败
					result.setMessage("发货单号(csourceid)不能为空！");
					WuYeWgptUtil.createResultEsbVO(esb);
					esb.getEsbInfo().setReturnStatus(IReturnStatus.ESB_FAILING);
					esb.getEsbInfo().setReturnMsg("失败");
					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().setReturnMsg("异常");
			esb.setResultInfo(result);// 设置响应内容
		} finally {
			rsdata = com.alibaba.fastjson.JSONObject.toJSONString(esb);

			WuYeWgptLogVO logVO = new WuYeWgptLogVO();
			logVO.setNc_id(nc_id);
			logVO.setOther_id(deliveryNum + " ");
			logVO.setBillno("");
			logVO.setTranstypecode("25");
			logVO.setItfcode("WGPT-NC-CG-003");
			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;
	}
	
	/**过滤掉已经结算的采购入库单的行
	 * @author 符耀铭
	 * @time 2019-12-19
	 * @param vos
	 * @return
	 * @throws BusinessException
	 */
	private PurchaseInVO[] filterHasInvoicePurchaseIn(PurchaseInVO[] vos) throws BusinessException{
		 Map<String, UFDouble> map = this.getNinvoicenumMap(vos);
	      List<PurchaseInVO> volist = new ArrayList<PurchaseInVO>();

	      for (PurchaseInVO vo : vos) {
	        PurchaseInBodyVO[] bodyvos = vo.getBodys();
	        List<PurchaseInBodyVO> list = new ArrayList<PurchaseInBodyVO>();
	        for (PurchaseInBodyVO bodyvo : bodyvos) {
	          // 1.过滤寄存供应商非空数据，寄存业务在消耗汇总处开票;2.赠品已经传存货核算，不需要开票(在sql中判断了)
	          if (!StringUtil.isSEmptyOrNull(bodyvo.getCvmivenderid())) {
	            continue;
	          }
	          // 过滤不可开票的行
	          if (this.canNinvoicenum(bodyvo, map.get(bodyvo.getCgeneralbid())))
	            list.add(bodyvo);
	        }
	        if (ValueCheckUtil.isNullORZeroLength(list))
	          continue;
	        vo.setChildrenVO(CollectionUtils.listToArray(list));
	        volist.add(vo);
	      }

	      return CollectionUtils.listToArray(volist);
	}
	
	/**
	   * 可开票数量=主数量-max(累计开票数量，累计结算数量)；开票以后不需要结算，结算过的不需要开票
	   * @author 符耀铭
	   * @time 2019-12-19
	   * @param bodyvo
	   * @param naccumsettlenum
	   * @return
	   */
	  private boolean canNinvoicenum(PurchaseInBodyVO bodyvo,
	      UFDouble naccumsettlenum) {

	    // max(累计开票数量，累计结算数量)
	    UFDouble tmp =
	        NCBaseTypeUtils
	            .isGt(
	                bodyvo.getNsignnum() == null ? UFDouble.ZERO_DBL : bodyvo
	                    .getNsignnum().abs(),
	                naccumsettlenum == null ? UFDouble.ZERO_DBL : naccumsettlenum
	                    .abs()) ? bodyvo.getNsignnum() : naccumsettlenum;
	    // 计算可开票数量
	    tmp = NCBaseTypeUtils.sub(bodyvo.getNnum(), tmp);

	    /**
	     * @author 符耀铭
	     * @time 2019-12-19
	     * 可开票条件：
	     * 入库数量>0;则可开票数量>0
	     * 入库数量<0;则可开票数量<0
	     * */
	    if (NCBaseTypeUtils.isLEZero(NCBaseTypeUtils.mult(tmp, bodyvo.getNnum())))
	      return false;
	    bodyvo.setNinvoicenum(tmp);
	    return true;
	  }
	
	  /**
	   * 获得入库单已结算数量
	   * @author 符耀铭
	   * @time 2019-12-19
	   * @param vos
	   * @return key:bid,value:结算数量
	   * @throws BusinessException
	   */
	  private Map<String, UFDouble> getNinvoicenumMap(PurchaseInVO[] vos)
	      throws BusinessException {
	    String[] bids =
	        VOEntityUtil.getVOsNotRepeatValue(VOEntityUtil.getBodyVOs(vos),
	            MetaNameConst.CGENERALBID);

	    return NCLocator.getInstance().lookup(IStockFinanceSettleInfoQuery.class)
	        .getTotalSettleNum(bids);
	  } 
public static void main(String[] args) {
	String billNo="D1202003030052728453";
	String[] arr = billNo.split(",");
	System.out.println(arr[0]);
}

@SuppressWarnings("restriction")
@Override
public void execFunction(HttpServletRequest request, HttpServletResponse response) {
	// TODO Auto-generated method stub
	initInvocationInfo();
	String jsondata = "";
	try {
		JSONObject jsonobj = WuYeWgptUtil.findPostJsonValue(request);// 获取请求值
		 jsondata = writeInvoiceInfo(jsonobj);
		
	} catch (BusinessException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}finally {
		sendResponse(response, jsondata);
	}
	
}
public String writeInvoiceInfo(final HttpServletRequest request) {
	try {
		initInvocationInfo();
		JSONObject jsonobj = WuYeWgptUtil.findPostJsonValue(request);// 获取Post请求的值
		return WuYeWgptUtil.getIWuYeWgptBusiService().writeInvoiceInfo(jsonobj);
	} catch (Exception e) {
		ResultEsbVO<ResultVO> esb = new ResultEsbVO<ResultVO>();
		ResultVO result = new ResultVO();
		esb.setResultInfo(result);
		result.setCode(IReturnStatus.ERROR);// 异常
		result.setError(WuYeWgptUtil.getExceptionDetail(e));
		WuYeWgptUtil.createResultEsbVO(esb);// 初始化响应对象
		esb.getEsbInfo().setReturnStatus(IReturnStatus.ESB_ERROR);
		esb.getEsbInfo().setReturnMsg("异常");
		esb.setResultInfo(result);// 设置响应内容
		String rsdata = com.alibaba.fastjson.JSONObject.toJSONString(esb);
		return rsdata;
	}
}
/**
 * 发送响应信息
 * @param response
 * @param esb
 */
private void sendResponse(final HttpServletResponse response, String jsondata) {
	PrintWriter out = null;
	try {
		response.setHeader("Content-type", "application/json;charset=UTF-8");
		out = new PrintWriter(new OutputStreamWriter(response.getOutputStream(), "UTF-8"));
		out.write(jsondata);
		out.flush();
	} catch (IOException e) {
		e.printStackTrace();
	} finally {
		if (out != null) {
			out.close();
		}
	}
}
private void initInvocationInfo(){
	try {
		IBusiCenterManageService busi = NCLocator.getInstance().lookup(IBusiCenterManageService.class);
		
		InvocationInfoProxy.getInstance().setUserDataSource(busi.getAvailableBusiCenterDsNames()[0]);
		InvocationInfoProxy.getInstance().setGroupId(SysInitQuery.getParaString("GLOBLE00000000000000", "GROUP"));
		InvocationInfoProxy.getInstance().setUserId(SysInitQuery.getParaString("GLOBLE00000000000000", "WYBCUSER"));
	} catch (BusinessException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	ISecurityTokenCallback tc = NCLocator.getInstance().lookup(ISecurityTokenCallback.class);
	byte[] token = tc.token("__system".getBytes(), "NC".getBytes());
	NetStreamContext.setToken(token);
}
}
