package nc.itf.fa.servlet;

import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;

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

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

import nc.bs.dao.BaseDAO;
import nc.bs.dao.DAOException;
import nc.bs.framework.adaptor.IHttpServletAdaptor;
import nc.bs.framework.common.NCLocator;
import nc.bs.framework.comn.NetStreamContext;
import nc.bs.framework.server.ISecurityTokenCallback;
import nc.bs.hz.utils.BillInfoQueryUtil;
import nc.bs.hz.utils.SafeObject;
import nc.bs.hz.utils.SendUtil;
import nc.bs.logging.Logger;
import nc.cmp.utils.BillcodeGenerater;
import nc.itf.fa.byzlog.IbyzLogRcord;
import nc.itf.uap.IUAPQueryBS;
import nc.itf.uap.pf.IPFBusiAction;
import nc.jdbc.framework.SQLParameter;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.util.fa.httputil.HttpCommnUtil;
import nc.vo.arap.receivable.AggReceivableBillVO;
import nc.vo.arap.receivable.ReceivableBillItemVO;
import nc.vo.arap.receivable.ReceivableBillVO;
import nc.vo.fa.byzLogVO.ByzLogRcordVO;
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 nccloud.bs.pub.pf.CloudPfUtil;
import uap.json.JSONObject;

public class ByzSysArapReciServlet implements IHttpServletAdaptor {

	// 获取数据库操作对象
	private BaseDAO baseDAO;

	// 设置能空的字段
	private Set<String> filter = new HashSet<String>(0);

	// Jaskson操作mapper
	private ObjectMapper mapper = new ObjectMapper();

	private BaseDAO getBaseDAO() {
		if (baseDAO == null) {
			baseDAO = new BaseDAO();
		}
		return baseDAO;
	}

	@Override
	public void doAction(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 后台模拟用户登录
		ISecurityTokenCallback tc = NCLocator.getInstance().lookup(ISecurityTokenCallback.class);
		  byte[] token = tc.token("__system".getBytes(), "NC".getBytes());
		  NetStreamContext.setToken(token);
//		NCLocator.getInstance().lookup(ISecurityTokenCallback.class).token("NCSystem".getBytes(), "pfxx".getBytes());
		// 配置初始化内容
		// LoginContext context = new LoginContext();
		// context.setPk_group(InvocationInfoProxy.getInstance().getGroupId());
		// context.setPk_loginUser(InvocationInfoProxy.getInstance().getUserId());
		ObjectNode returnJson = mapper.createObjectNode();
		String src_code = null;
		ObjectNode jsonNode = (ObjectNode) mapper.readTree(HttpCommnUtil.requestJson(req));
		try {
			JSONObject jsonObject = new JSONObject(jsonNode.toString());
			JSONObject jsonohead = jsonObject.getJSONObject("data").getJSONObject("head");
			BillInfoQueryUtil.initEnvironment("0001H810000000000HS2", new UFDate(jsonohead.getString("billdate")));
			BillInfoQueryUtil.initSysBilltypeCache(new String[] { "F0" });
			// 默认登陆:获取附件流需要登陆的token
//			IFwLogin loginService = NCLocator.getInstance().lookup(IFwLogin.class);
//			String user = NCLocator.getInstance().lookup(ISysInitDAO.class).getSysInitTempVO("loginuser")
//					.getDefaultvalue();
//			String password = NCLocator.getInstance().lookup(ISysInitDAO.class).getSysInitTempVO("loginpass")
//					.getDefaultvalue();
//			byte[] token = loginService.login(user, password, null);
//			NetStreamContext.setToken(token);
			// JSONObject.parseObject(Base64Util.decode(json.getString("data")));
			// Base64解密data
			JsonNode data = mapper.readTree(mapper.writeValueAsString(jsonNode.get("data")));
			// 替换原加密的data
			jsonNode.replace("data", data);
			// 检查是否有空值
			checkItem(jsonNode);
			String head = mapper.writeValueAsString(jsonNode.findValue("head"));
			JsonNode bodys = jsonNode.findValue("bodys");
			int len = bodys.size();
			// 应收单表头
			ReceivableBillVO billVO = setReceivableBillVO(head);
			// 应收单表体
			ReceivableBillItemVO[] itemVOs = new ReceivableBillItemVO[len];
			for (int i = 0; i < len; i++) {
				String body = mapper.writeValueAsString(bodys.get(i));
				itemVOs[i] = setReceivableBillItemVO(billVO, body);
			}
			// 封装聚合VO
			AggReceivableBillVO aggvo = new AggReceivableBillVO();
			aggvo.setParentVO(billVO);
			aggvo.setChildrenVO(itemVOs);
			IPFBusiAction ipf = NCLocator.getInstance().lookup(IPFBusiAction.class);
			// 执行保存动作
			ipf.processAction("SAVE", "F0", null, aggvo, null, null);
			// 判断是否有审批流
			//modefy by djy 20220305 方案更改不要审批流，自由态
//			if (CloudPfUtil.hasApproveflowDef("F0-Cxx-W63", aggvo)) {
//				// 执行提交动作
//				ipf.processAction("COMMIT", "F0", null, aggvo, null, null);
//			} else {
				// 执行审批动作
//				ipf.processAction("APPROVE", "F0", null, aggvo, null, null);
//			}

			// 返回单据编号
			src_code = billVO.getDef57();
			returnJson.put("billno", billVO.getBillno());
			returnJson.put("billpk", billVO.getPrimaryKey());
			returnJson.put("guid", src_code);
			returnJson.put("message", "固定资产应收单新增成功。");
			returnJson.put("status", 1);
		} catch (Exception e) {
			e.printStackTrace();
			// 返回错误信息
			returnJson.put("message", e.getMessage());
			returnJson.put("status", 0);
		} finally {
			String result = mapper.writeValueAsString(returnJson);
			HttpCommnUtil.responseWriter(resp, result);
			IbyzLogRcord ibyzLogRcord = (IbyzLogRcord) NCLocator.getInstance().lookup(IbyzLogRcord.class);
			ByzLogRcordVO byzLogRcordVO = new ByzLogRcordVO();
			byzLogRcordVO.setVbillcode(src_code);
			byzLogRcordVO.setItf_type("碧优资应收单保存到NC");
			byzLogRcordVO.setItfclass(this.getClass().toString());			
			byzLogRcordVO.setNcctobyzresult(SendUtil.unicodeToString(result));
			byzLogRcordVO.setByztonccparam(SendUtil.unicodeToString(mapper.writeValueAsString(jsonNode)));
			// byzLogRcordVO.setItfaddress(arcip);
			try {
				ibyzLogRcord.RcordLogBYZ__RequiresNew(byzLogRcordVO);
			} catch (BusinessException e) {
				Logger.error(e.getMessage(), e);
				Logger.error("日志生成失败！！nc.itf.fa.byzlog.IbyzLogRcord");
			}
		}
	}

	//查询业务场景档案
	private String getYwcj(String code) throws BusinessException{
		String pk_defoc="";
		String sql = "select pk_defdoc from bd_defdoc where pk_defdoclist=(select pk_defdoclist from bd_defdoclist where code='YWCJ' and nvl(dr,0)=0) and nvl(dr,0)=0  and enablestate=2 "
				+ "and code='" + code + "'";
		pk_defoc=(String) NCLocator.getInstance().lookup(IUAPQueryBS.class).executeQuery(sql, new ColumnProcessor());
		return pk_defoc;
	}
	
	/**
	 * 查询税码
	 * 
	 * @param code
	 * @return
	 * @throws DAOException
	 */
	private String getPk_taxcode(String code) throws BusinessException {
		String sql = "SELECT PK_TAXCODE FROM BD_TAXCODE WHERE CODE = ?";
		String result = getColumn(sql, code);
		if (result == null) {
			throw new BusinessException("没有找到该税码(taxcodeid),请检查数据:" + code);
		}
		return result;
	}

	/**
	 * 查询客户
	 * 
	 * @param code
	 * @return
	 * @throws BusinessException
	 */
	private String getPk_customer(String code) throws BusinessException {
		String sql = "SELECT PK_CUSTOMER FROM BD_CUSTOMER WHERE CODE = ?";
		String result = getColumn(sql, code);
		if (result == null) {
			throw new BusinessException("没有找到该客户(customer),请检查数据:" + code);
		}
		return result;
	}

	/**
	 * 查询币种
	 * 
	 * @param code 币种名称
	 * @return 币种主键
	 * @throws DAOException
	 */
	private String getPk_currtype(String code) throws BusinessException {
		String sql = "SELECT PK_CURRTYPE FROM BD_CURRTYPE WHERE NAME = ? AND NVL(DR,0) = 0";
		String result = getColumn(sql, code);
		if (result == null) {
			throw new BusinessException("没有找到该币种名称(pk_currtype),请检查数据:" + code);
		}
		return result;
	}

	/**
	 * 查询单据类型
	 * 
	 * @param code 单据类型编码
	 * @return 单据类型主键
	 * @throws DAOException
	 */
	private String getPk_tradetypeid(String code) throws BusinessException {
		String sql = "SELECT PK_BILLTYPEID FROM BD_BILLTYPE WHERE PK_BILLTYPECODE = ? AND NVL(DR,0) = 0";
		String result = getColumn(sql, code);
		if (result == null) {
			throw new BusinessException("没有找到该单据类型编码(pk_billtypeid),请检查数据:" + code);
		}
		return result;
	}

	/**
	 * 根据组织查询集团
	 * 
	 * @param code 组织PK
	 * @return
	 * @throws DAOException
	 */
	private String getPk_group(String pk) throws BusinessException {
		String sql = "SELECT PK_GROUP FROM ORG_ORGS WHERE PK_ORG = ? AND NVL(DR,0) = 0";
		String result = getColumn(sql, pk);
		if (result == null) {
			throw new BusinessException("没有找到该财务组织(pk_org),请检查数据:" + pk);
		}
		return result;
	}

	/**
	 * 查询财务组织
	 * 
	 * @param code 财务组织编码
	 * @return 财务组织主键
	 * @throws DAOException
	 */
	private String getPk_org(String pk) throws BusinessException {
		String sql = "SELECT PK_ORG FROM ORG_ORGS_V WHERE PK_VID = ? AND NVL(DR,0) = 0";
		String result = getColumn(sql, pk);
		if (result == null) {
			throw new BusinessException("没有找到该财务组织版本(pk_org_v),请检查数据:" + pk);
		}
		return result;

	}

	/**
	 * 查询外部制单人
	 * 
	 * @return
	 * @throws DAOException
	 */
	private String getCreator(String code) throws BusinessException {
		String sql = "SELECT CUSERID FROM SM_USER WHERE USER_CODE = ? AND NVL(DR,0) = 0";
		String result = getColumn(sql, code);
		if (result == null) {
			throw new BusinessException("没有找到该制单人(billmaker),请检查数据:" + code);
		}
		return result;
	}

	/**
	 * 判断单据接收唯一
	 * 
	 * @param src_id
	 * @throws BusinessException
	 */
	private void selectOnlyID(String src_id) throws BusinessException {
		String sql = "SELECT DEF57 FROM AR_RECBILL WHERE DEF57 = ? AND NVL(DR,0) = 0";
		String result = getColumn(sql, src_id);
		if (result != null) {
			throw new BusinessException("来源单据号(def57)已存在,请检查数据:" + src_id);
		}
	}

	/**
	 * 应收单表头
	 * 
	 * @return
	 * @throws IOException
	 * @throws JsonMappingException
	 * @throws JsonParseException
	 * @throws BusinessException
	 * @throws Exception
	 */
	private ReceivableBillVO setReceivableBillVO(String head)
			throws JsonParseException, JsonMappingException, IOException, BusinessException {
		mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		ReceivableBillVO vo = mapper.readValue(head, ReceivableBillVO.class);
		// 判断单据接收唯一
		selectOnlyID(vo.getDef57());
		// 财务组织版本
		// String pk_org_v = vo.getPk_org_v();
		// 财务组织
		// vo.setPk_org(getPk_org(pk_org_v));
		// 集团
		vo.setPk_group(getPk_group(vo.getPk_org()));
		// 应收类型
		vo.setPk_tradetype("F0-Cxx-W63");
		// 应收类型id
		vo.setPk_tradetypeid(getPk_tradetypeid("F0-Cxx-W63"));
		// 币种
		vo.setPk_currtype(getPk_currtype(vo.getPk_currtype()));
		// 客户
		vo.setCustomer(getPk_customer(vo.getCustomer()));
		// 单据状态
		vo.setBillstatus(-1);
		// 审批状态
		// vo.setApprovestatus(3);
		// 制单人
		vo.setBillmaker(getCreator("ARC"));
		// 创建人
		vo.setCreator(vo.getBillmaker());
		// 创建时间
		vo.setCreationtime(new UFDateTime());
		// 期初标志
		vo.setIsinit(UFBoolean.FALSE);
		// 单据大类
		vo.setBillclass("ys");
		// 单据类型
		vo.setPk_billtype("F0");
		// 冻结状态
		vo.setSaga_frozen(0);
		// 事务状态
		vo.setSaga_status(0);
		vo.setRate(new UFDouble(1));
		// 往来对象
		vo.setObjtype(0);
		// 单据所属系统
		vo.setSyscode(0);
		//业务场景
		if(vo.getDef80()!=null)
			vo.setDef80(getYwcj(vo.getDef80()));
		
		// 来源系统
		vo.setSrc_syscode(0);
		// 单据号
		String billcode = new BillcodeGenerater().getBillCode("F0", vo.getPk_group(), vo.getPk_org(), null, null);
		vo.setBillno(billcode);
		return vo;
	}

	/**
	 * 应收单表体
	 * 
	 * @return
	 * @throws BusinessException
	 * @throws IOException
	 * @throws JsonMappingException
	 * @throws JsonParseException
	 */
	private ReceivableBillItemVO setReceivableBillItemVO(ReceivableBillVO head, String body)
			throws BusinessException, JsonParseException, JsonMappingException, IOException {
		ReceivableBillItemVO vo = mapper.readValue(body, ReceivableBillItemVO.class);
		// 集团
		vo.setPk_group(head.getPk_group());
		// 组织
		vo.setPk_org(head.getPk_org());
		// 组织版本
		vo.setPk_org_v(head.getPk_org_v());
		// 客户
		vo.setCustomer(getPk_customer(vo.getCustomer()));
		// 税码
		// vo.setTaxcodeid(getPk_taxcode(vo.getTaxcodeid()));
		// 单据大类
		vo.setBillclass(head.getBillclass());
		// 单据日期
		vo.setBilldate(head.getBilldate());
		// 方向
		vo.setDirection(1);
		// 单据类型
		vo.setPk_billtype(head.getPk_billtype());
		// 应收类型
		vo.setPk_tradetype(head.getPk_tradetype());
		// 应收类型id
		vo.setPk_tradetypeid(head.getPk_tradetypeid());
		// 往来对象
		vo.setObjtype(0);
		// 币种
		vo.setPk_currtype(head.getPk_currtype());
		// 本币
		vo.setLocal_money_de(vo.getMoney_de());
		// 单据号
		vo.setBillno(head.getBillno());
		vo.setRate(new UFDouble(1));
		return vo;
	}

	/**
	 * 单值通用查询
	 * 
	 * @param sql
	 * @param code
	 * @return
	 * @throws DAOException
	 */
	private String getColumn(String sql, String code) throws DAOException {
		SQLParameter parameter = new SQLParameter();
		parameter.addParam(code);
		return SafeObject.toString(getBaseDAO().executeQuery(sql, parameter, new ColumnProcessor()));
	}

	/**
	 * 判断JSON是否有值为空
	 * 
	 * @param jsonObject
	 * @throws BusinessException
	 * @throws JsonProcessingException
	 */
	private void checkItem(JsonNode node) throws JsonProcessingException, BusinessException {
		// 判断是否存在下一节点否则跳出递归
		if (node.isValueNode()) {
			return;
		}

		if (node.isObject()) {
			Iterator<Entry<String, JsonNode>> it = node.fields();
			while (it.hasNext()) {
				Entry<String, JsonNode> entry = it.next();
				if (entry.getValue().toString().equals("\"\"") || entry.getValue().isNull()) {
					throw new BusinessException(entry.getKey() + "不存在或null");
				}
				checkItem(entry.getValue());
			}
		}

		if (node.isArray()) {
			Iterator<JsonNode> it = node.iterator();
			while (it.hasNext()) {
				checkItem(it.next());
			}
		}
	}
}