package nc.impl.arap.nc63.bill;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;

import nc.bs.arap.gathering.bgtask.process.NC63F4ToNCCF2PullBillProcess;
import nc.bs.arap.pay.bgtask.process.NC63F5ToNCCF3PullBillProcess;
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.itf.arap.nc63.bill.IPullNC63Bill;
import nc.itf.uap.pf.IWorkflowDefine;
import nc.itf.uap.pf.IWorkflowMachine;
import nc.itf.uap.pf.IplatFormEntry;
import nc.itf.uap.pf.metadata.IFlowBizItf;
import nc.log.arap.bill.WYNCCARAPLogger;
import nc.uap.pf.metadata.PfMetadataTools;
import nc.vo.arap.gathering.AggGatheringBillVO;
import nc.vo.arap.nc63.gathering.CMPRecBillDetailVO_NC63;
import nc.vo.arap.nc63.gathering.CMPRecBillVO_NC63;
import nc.vo.arap.nc63.pay.CMPPayBillDetailVO_NC63;
import nc.vo.arap.nc63.pay.CMPPaybillVO_NC63;
import nc.vo.arap.pay.AggPayBillVO;
import nc.vo.pf.pub.util.SQLUtil;
import nc.vo.pub.AggregatedValueObject;
import nc.vo.pub.BusinessException;
import nc.vo.pub.CircularlyAccessibleValueObject;
import nc.vo.pub.SuperVO;
import nc.vo.pub.workflownote.WorkflownoteVO;
import nc.vo.pubapp.pattern.model.entity.bill.AbstractBill;
import nc.vo.uap.pf.PFRuntimeException;
import nc.vo.uap.pf.PfProcessBatchRetObject;
import nc.vo.wfengine.core.workflow.WorkflowProcess;
import nc.vo.wfengine.definition.WorkflowTypeEnum;
import nccloud.vo.pf.flowinstance.NCCFlowInstanceVO;
/**
 * @Description: 
 * 		【拉取NC633内转收[F4-Cxx-2 内部单位转账（收方）]->NCC收款单[F2-Cxx-01 收款单（内转）]】
 * 		【拉取NC633内转付[F5-Cxx-2 内部单位转账（付方）]->NCC付款单[F3-Cxx-D01 付款单（内转）]】
 * @author 谢文如 【碧桂园物业NCC】
 * @date 2020-11-23
 * @version with NCC V2005
 */
public class PullNC63BillImpl implements IPullNC63Bill {

	@Override
	public int pullBill_RequiresNew(LinkedHashMap<String, Object> paraMap) throws BusinessException {
		Object nc63DataSource = paraMap.get("nc63DataSource");
		Object nccTradeType = paraMap.get("nccTradeType");

		BaseDAO nc63Dao = new BaseDAO(nc63DataSource.toString());
		BaseDAO nccDao = new BaseDAO();
		int count = 0;
		if ("F2-Cxx-01".equals(nccTradeType)) {
			// 收款单内转
			/** 1.NC63表头 **/
			List<CMPRecBillVO_NC63> nc63HeadVOList = NC63F4ToNCCF2PullBillProcess.queryHead(nc63Dao, nccDao, paraMap);
			if (nc63HeadVOList == null || nc63HeadVOList.size() == 0) {
				return count;
			}
			/** 2.NC63表体 **/
			List<CMPRecBillDetailVO_NC63> nc63BodyList = NC63F4ToNCCF2PullBillProcess.queryBody(nc63Dao, nccDao, paraMap,
					nc63HeadVOList);
			if (nc63BodyList == null || nc63BodyList.size() == 0) {
				return count;
			}
			//覆盖：删除已经存在的数据
			if(nc63HeadVOList!=null && nc63HeadVOList.size()>0) {
				/** 3.查询NCC已经存在的数据 **/
				List<String> nc63HidList = nc63HeadVOList.stream().map(CMPRecBillVO_NC63::getPk_recbill).collect(Collectors.toList());
				String wheresql = SQLUtil.buildSqlForIn("pk_recbill", nc63HidList.toArray(new String[0]));
				String sql = "delete nc63_cmp_recbill where "+wheresql;
				nccDao.executeUpdate(sql);
				sql = "delete nc63_cmp_recbilldetail where "+wheresql;
				nccDao.executeUpdate(sql);
			}
			// 插入NCC
			nccDao.insertVOArrayWithPK(nc63HeadVOList.toArray(new CMPRecBillVO_NC63[0]));
			nccDao.insertVOArrayWithPK(nc63BodyList.toArray(new CMPRecBillDetailVO_NC63[0]));
			count = nc63HeadVOList.size();
		} else if ("F3-Cxx-D01".equals(nccTradeType)) {
			// 付款单内转
			/** 1.NC63表头 **/
			List<CMPPaybillVO_NC63> nc63HeadVOList = NC63F5ToNCCF3PullBillProcess.queryHead(nc63Dao, nccDao, paraMap);
			if (nc63HeadVOList == null || nc63HeadVOList.size() == 0) {
				return count;
			}
			/** 2.NC63表体 **/
			List<CMPPayBillDetailVO_NC63> nc63BodyList = NC63F5ToNCCF3PullBillProcess.queryBody(nc63Dao, nccDao, paraMap,
					nc63HeadVOList);
			if (nc63BodyList == null || nc63BodyList.size() == 0) {
				return count;
			}
			//覆盖：删除已经存在的数据
			if(nc63HeadVOList!=null && nc63HeadVOList.size()>0) {
				/** 3.查询NCC已经存在的数据 **/
				List<String> nc63HidList = nc63HeadVOList.stream().map(CMPPaybillVO_NC63::getPk_paybill).collect(Collectors.toList());
				String wheresql = SQLUtil.buildSqlForIn("pk_paybill", nc63HidList.toArray(new String[0]));
				String sql = "delete nc63_cmp_paybill where "+wheresql;
				nccDao.executeUpdate(sql);
				sql = "delete nc63_cmp_paybilldetail where "+wheresql;
				nccDao.executeUpdate(sql);
			}
			// 插入NCC
			nccDao.insertVOArrayWithPK(nc63HeadVOList.toArray(new CMPPaybillVO_NC63[0]));
			nccDao.insertVOArrayWithPK(nc63BodyList.toArray(new CMPPayBillDetailVO_NC63[0]));
			count = nc63HeadVOList.size();
		}

		return count;
	}

	@Override
	public SuperVO makeBill_RequiresNew(AbstractBill bill) {
		SuperVO rsVO = null;
		try {
			CircularlyAccessibleValueObject headVO = bill.getParentVO();
			String pk_tradetype = headVO.getAttributeValue("pk_tradetype").toString();
			String pk_billtype = headVO.getAttributeValue("pk_billtype").toString();
			if ("F2-Cxx-01".equals(pk_tradetype)) {
				rsVO = new CMPRecBillVO_NC63();
				rsVO.setAttributeValue("pk_recbill", headVO.getAttributeValue("def12").toString());
			} else if ("F3-Cxx-D01".equals(pk_tradetype)) {
				rsVO = new CMPPaybillVO_NC63();
				rsVO.setAttributeValue("pk_paybill", headVO.getAttributeValue("def34").toString());
			}
			
			HashMap<String, Object> eParam = new HashMap<String, Object>();
			String actionCode = "SAVE";
			headVO.setAttributeValue("creator", InvocationInfoProxy.getInstance().getUserId());
			headVO.setAttributeValue("billmaker", InvocationInfoProxy.getInstance().getUserId());
			IplatFormEntry platFormEntry = NCLocator.getInstance().lookup(IplatFormEntry.class);
			IWorkflowMachine workflowMachine = NCLocator.getInstance().lookup(IWorkflowMachine.class);
			// 保存
			Object objBill = platFormEntry.processAction(actionCode, pk_tradetype, null, bill, null, null);
			bill = objToAbstractBill(pk_tradetype, objBill);
			// 提交
			actionCode = "COMMIT" + InvocationInfoProxy.getInstance().getUserId();
			// 判断是否定义审批流
			boolean hasFlow = hasApproveflowDef(pk_tradetype, bill);
			if (hasFlow) {
				// 有，则走提交动作脚本
				eParam.put("NCCLOUD_ENTRY", Boolean.valueOf(true));
				eParam.put("IS_RELOADBILL", Boolean.valueOf(true));
				WorkflownoteVO worknoteVO = workflowMachine.checkWorkFlow(actionCode, pk_billtype, bill, eParam);
				objBill = platFormEntry.processAction(actionCode, pk_tradetype, worknoteVO, bill, null, eParam);
				// 审批
				bill = objToAbstractBill(pk_tradetype, objBill);
				if (Integer.valueOf(bill.getParentVO().getAttributeValue("approvestatus").toString()) != 1) {
					// 审批
					actionCode = "APPROVE";
					worknoteVO = workflowMachine.checkWorkFlow(actionCode, pk_billtype, bill, eParam);
					if (worknoteVO != null) {
						worknoteVO.setApproveresult("Y");
						worknoteVO.setChecknote("自动审批通过");
					}
					objBill = platFormEntry.processAction(actionCode, pk_tradetype, worknoteVO, bill, null, eParam);
				}
			} else {
				// 没有，则提交即审批
				HashMap<String, Object> extParam = new HashMap<String, Object>();
				extParam.put("IS_RELOADBILL", true);
				extParam.put("batch", Boolean.valueOf(true));
				extParam.put("NCCLOUD_ENTRY", Boolean.valueOf(true));
				extParam.put("CommitNoFlowBatch", Boolean.valueOf(true));

				WorkflownoteVO worknoteVO = new WorkflownoteVO();
				AbstractBill[] bills = new AbstractBill[] { bill };
				objBill = platFormEntry.processCommitNoFlowBatch4NCC(actionCode, pk_tradetype, worknoteVO, bills, null,
						extParam);
			}
			// 更新中间表状态
			rsVO.setAttributeValue("state", "Y");
		} catch (Exception e) {
			e.printStackTrace();
			WYNCCARAPLogger.log("PullNC63BillImpl", "后台任务拉取NC63内转生成NCC内转", e, JSON.toJSONString(bill));
			rsVO.setAttributeValue("state", "N");
			rsVO.setAttributeValue("msg", e.getMessage());
		} finally {
			String msg = (String) rsVO.getAttributeValue("msg");
			rsVO.setAttributeValue("msg", substring(msg, 3000));
		}
		return rsVO;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public SuperVO delBill_RequiresNew(AbstractBill bill) {
		SuperVO rsVO = null;
		try {
			CircularlyAccessibleValueObject headVO = bill.getParentVO();
			String pk_tradetype = headVO.getAttributeValue("pk_tradetype").toString();
			if ("F2-Cxx-01".equals(pk_tradetype)) {
				rsVO = new CMPRecBillVO_NC63();
				rsVO.setAttributeValue("state", "Y");
				rsVO.setAttributeValue("pk_recbill", headVO.getAttributeValue("def12").toString());
			} else if ("F3-Cxx-D01".equals(pk_tradetype)) {
				rsVO = new CMPPaybillVO_NC63();
				rsVO.setAttributeValue("state", "Y");
				rsVO.setAttributeValue("pk_paybill", headVO.getAttributeValue("def34").toString());
			}
			HashMap<String, Object> eParam = new HashMap<String, Object>();
			IplatFormEntry platFormEntry = NCLocator.getInstance().lookup(IplatFormEntry.class);
			// 判断是否定义审批流
			boolean hasFlow = hasApproveflowDef(pk_tradetype, bill);
			if(hasFlow) {
				// 取消审批
				String actionCode = "UNAPPROVE";
				if (Integer.valueOf(bill.getParentVO().getAttributeValue("approvestatus").toString()) == 1) {
					WorkflownoteVO worknoteVO = new WorkflownoteVO();
					StringBuffer where = new StringBuffer("");
					where.append(" pk_billtype = '"+pk_tradetype+"'").append("\r\n");
					where.append("  and billversionpk = '"+bill.getPrimaryKey()+"'").append("\r\n");
					where.append("  and ismsgbind = 'N'").append("\r\n");
					where.append("  and workflow_type = 2").append("\r\n");
					where.append("  and actiontype <> 'BIZ'").append("\r\n");
					where.append("  and approvestatus = 1"); 
					List<WorkflownoteVO> co = (List<WorkflownoteVO>)new BaseDAO().retrieveByClause(WorkflownoteVO.class, where.toString());
					if(co!=null && co.size()>0) {
						worknoteVO = co.get(0);
					}
					List<Map<String, Object>> paraMapList = new ArrayList();
					Map paraMap = new HashMap();
				    paraMap.put("NCCFlowParamter", "NCCloud");
				    paraMapList.add(paraMap);
			    	HashMap hashmap = new HashMap();
			    	hashmap.put("NCCLOUD_ENTRY", Boolean.valueOf(true));
					Object objBill = platFormEntry.processAction(actionCode, pk_tradetype, worknoteVO, bill, paraMapList, hashmap);
					if ("F2-Cxx-01".equals(pk_tradetype)) {
						bill = (AggGatheringBillVO)((AggregatedValueObject[])objBill)[0];
					} else if ("F3-Cxx-D01".equals(pk_tradetype)) {
						bill = (AggPayBillVO)((AggregatedValueObject[])objBill)[0];
					}
				}
				//收回
				actionCode = "UNCOMMIT";
				if (Integer.valueOf(bill.getParentVO().getAttributeValue("approvestatus").toString()) == 3) {
					WorkflownoteVO worknoteVO = new WorkflownoteVO();
					StringBuffer where = new StringBuffer("");
					where.append(" pk_billtype = '"+pk_tradetype+"'").append("\r\n");
					where.append("  and billversionpk = '"+bill.getPrimaryKey()+"'").append("\r\n");
					where.append("  and ismsgbind = 'N'").append("\r\n");
					where.append("  and workflow_type = 2").append("\r\n");
					where.append("  and actiontype <> 'BIZ'").append("\r\n");
					where.append("  and approvestatus = 0"); 
					List<WorkflownoteVO> co = (List<WorkflownoteVO>)new BaseDAO().retrieveByClause(WorkflownoteVO.class, where.toString());
					if(co!=null && co.size()>0) {
						worknoteVO = co.get(0);
					}
					Object objBill = platFormEntry.processAction(actionCode, pk_tradetype, worknoteVO, bill, null, eParam);
					bill = objToAbstractBill(pk_tradetype, objBill); 
				}
				 //删除
				 actionCode = "DELETE";
				 WorkflownoteVO worknoteVO = new WorkflownoteVO();
				 platFormEntry.processAction(actionCode, pk_tradetype, worknoteVO, bill, null, eParam);
				System.out.println();
			}else {
				String actionCode = "UNCOMMIT";
				WorkflownoteVO worknoteVO = new WorkflownoteVO();
				if (Integer.valueOf(bill.getParentVO().getAttributeValue("approvestatus").toString()) == 1) {
					HashMap<String, Object> extParam = new HashMap<String, Object>();
					extParam.put("IS_RELOADBILL", true);
					extParam.put("batch", Boolean.valueOf(true));
					extParam.put("NCCLOUD_ENTRY", Boolean.valueOf(true));
					extParam.put("IS_UNSAVENOFlOW", Boolean.valueOf(true));
					
					AbstractBill[] bills = new AbstractBill[] { bill };
					Object objBill = platFormEntry.processUnSaveNoFlowBatch4NCC(actionCode, pk_tradetype, worknoteVO, bills, null, extParam);
					PfProcessBatchRetObject retObject = (PfProcessBatchRetObject)objBill;
					objBill = retObject.getRetObj();
					bill = objToAbstractBill(pk_tradetype, objBill); 
				}
				 //DELETE
				 actionCode = "DELETE";
				 platFormEntry.processAction(actionCode, pk_tradetype, worknoteVO, bill, null, eParam);
				System.out.println();
			}
		} catch (Exception e) {
			e.printStackTrace();
			WYNCCARAPLogger.log("PullNC63BillImpl", "后台任务拉取NC63内转生成NCC内转", e, JSON.toJSONString(bill));
			rsVO.setAttributeValue("msg", e.getMessage());
		} finally {
			String msg = (String) rsVO.getAttributeValue("msg");
			rsVO.setAttributeValue("msg", substring(msg, 3000));
		}
		return rsVO;
	}
	
	private String substring(String s, int length) {
		try {
			if (s == null || s.length()==0) {
				return s;
			}
			int len = s.getBytes("UTF-8").length;
			if (len < 3000) {
				return s;
			}
			byte[] bytes = s.getBytes("Unicode");
			int n = 0; // 表示当前的字节数
			int i = 2; // 要截取的字节数，从第3个字节开始
			for (; i < bytes.length && n < length; i++) {
				// 奇数位置，如3、5、7等，为UCS2编码中两个字节的第二个字节
				if (i % 2 == 1) {
					n++; // 在UCS2第二个字节时n加1
				} else {
					// 当UCS2编码的第一个字节不等于0时，该UCS2字符为汉字，一个汉字算两个字节
					if (bytes[i] != 0) {
						n++;
					}
				}
			}
			// 如果i为奇数时，处理成偶数
			if (i % 2 == 1) {
				// 该UCS2字符是汉字时，去掉这个截一半的汉字
				if (bytes[i - 1] != 0) {
					i = i - 1;
				}
				// 该UCS2字符是字母或数字，则保留该字符
				else {
					i = i + 1;
				}
			}
			return new String(bytes, 0, i, "Unicode");
		} catch (Exception e) {

		}
		return s;
	}

	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;
	}

	private AbstractBill objToAbstractBill(String nccTradeType, Object objBill) {
		AbstractBill bill = null;
		if ("F2-Cxx-01".equals(nccTradeType)) {
			AggGatheringBillVO[] aggVOs = (AggGatheringBillVO[]) objBill;
			bill = aggVOs[0];
		} else if ("F3-Cxx-D01".equals(nccTradeType)) {
			AggPayBillVO[] aggVOs = (AggPayBillVO[]) objBill;
			bill = aggVOs[0];
		}
		return bill;
	}

}
