package nccloud.pubimpl.gl.lightgl.voucher;

import com.yonyou.cloud.ncc.NCCEnv;
import com.yonyou.cloud.ncc.NCCSagas;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import nc.bs.dao.BaseDAO;
import nc.bs.framework.common.InvocationInfoProxy;
import nc.bs.framework.common.NCLocator;
import nc.bs.gl.voucher.VoucherBO;
import nc.bs.gl.voucher.VoucherPxjz;
import nc.bs.ml.NCLangResOnserver;
import nc.gl.utils.GLMultiLangUtil;
import nc.itf.gl.voucher.IVoucher;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.pubitf.fip.service.IFipMessageSagasCheckService;
import nc.vo.gateway60.accountbook.AccountBookUtil;
import nc.vo.gl.pubvoucher.DetailVO;
import nc.vo.gl.pubvoucher.OperationResultVO;
import nc.vo.gl.pubvoucher.VoucherVO;
import nc.vo.jcom.lang.StringUtil;
import nc.vo.org.AccountingBookVO;
import nc.vo.pub.BusinessException;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFDateTime;
import nc.vo.pub.lang.UFDouble;
import nccloud.bs.gl.voucher.AccountingbookQryBO;
import nccloud.bs.gl.voucher.ApportionBO;
import nccloud.bs.gl.voucher.BotCreateVouhcerBO;
import nccloud.bs.gl.voucher.VoucherWebBO;
import nccloud.bs.gl.voucher.VoucherWebQryBO;
import nccloud.dto.gl.lightgl.VoucherDetailMDVO;
import nccloud.dto.gl.lightgl.VoucherMDVO;
import nccloud.dto.gl.lightgl.VoucherWebVO;
import nccloud.itf.gl.voucherapi.IVoucherRestService;
import nccloud.pubimpl.gl.account.AccountRepUtil;
import nccloud.pubitf.gl.lightgl.voucher.IVoucherWebService;

public class VoucherWebServiceImpl implements IVoucherWebService {
	
	public Map<String, Object> insertVoucher(VoucherVO voucherVO, boolean isAdd, UFDate busidate)
			throws BusinessException {
		voucherVO.setPk_voucher((String) null);
		this.newSaga4FipRelation(voucherVO);
		return (new VoucherWebBO()).saveVoucher(voucherVO, isAdd, busidate);
	}

	public Map<Integer, String> saveAllVoucher(Map<Integer, VoucherVO> voucherVOMap) throws BusinessException {
		if (voucherVOMap != null && voucherVOMap.size() != 0) {
			List<VoucherVO> voucherVOs = new ArrayList(voucherVOMap.size());
			Iterator var3 = voucherVOMap.keySet().iterator();

			while (var3.hasNext()) {
				Integer row = (Integer) var3.next();
				VoucherVO voucher = (VoucherVO) voucherVOMap.get(row);
				voucherVOs.add(voucher);
			}

			this.newSaga4FipRelation((VoucherVO[]) voucherVOs.toArray(new VoucherVO[voucherVOs.size()]));
			Map<Integer, String> rtMap = new HashMap();
			Iterator var10 = voucherVOMap.keySet().iterator();

			while (var10.hasNext()) {
				Integer row = (Integer) var10.next();
				VoucherVO voucher = (VoucherVO) voucherVOMap.get(row);
				if (voucher.getDetail() == null || voucher.getDetail().size() == 0) {
					throw new BusinessException(
							NCLangResOnserver.getInstance().getStrByID("20021005", "UPP20021005-000612"));
				}

				(new VoucherWebBO()).setDefaultValue(voucher);
				OperationResultVO[] results = ((IVoucher) NCLocator.getInstance().lookup(IVoucher.class)).save(voucher,
						Boolean.TRUE);
				String m_strPK = results[0].m_strPK;
				rtMap.put(row, m_strPK);
			}

			return rtMap;
		} else {
			return null;
		}
	}

	private void newSaga4FipRelation(VoucherVO... vouchers) throws BusinessException {
		boolean needSaga = false;
		List<String> relationPKs = new ArrayList(vouchers.length);
		if (!NCCEnv.isMerged()) {
			for (int i = 0; i < vouchers.length; ++i) {
				VoucherVO voucher = vouchers[i];
				if (voucher.getFipInfo() != null && voucher.getFipInfo() instanceof String[]) {
					String[] pk_relation = (String[]) ((String[]) voucher.getFipInfo());
					if (pk_relation != null && pk_relation.length > 0) {
						needSaga = true;
						relationPKs.addAll(Arrays.asList(pk_relation));
					}
				}
			}
		}

		if (needSaga && !relationPKs.isEmpty()) {
			NCCSagas.startNewSaga();
			((IFipMessageSagasCheckService) NCLocator.getInstance().lookup(IFipMessageSagasCheckService.class))
					.validateDelOperSagasCheck((String[]) relationPKs.toArray(new String[relationPKs.size()]));
		}

	}

	public Map<String, Object> tempSaveVoucher(VoucherWebVO voucherWebVO) throws BusinessException {
		return (new VoucherWebBO()).tempSaveVoucher(voucherWebVO);
	}

	public Map<String, Object> updateVoucher(VoucherVO voucherVO, boolean isAdd, UFDate busidate)
			throws BusinessException {
		if (voucherVO == null) {
			return null;
		}

		// 【双百】2020-11-16：NC63推送过来的凭证只能修改：单据日期、凭证号两个字段【开始】
		IVoucher vouser = NCLocator.getInstance().lookup(IVoucher.class);
		String billno = voucherVO.getFree3(); // 单据号：单据号不空，说明是NC63推送过来的凭证
		if (billno != null && !"".equals(billno.trim())) {
			VoucherVO[] varray = vouser.queryByPks(new String[] { voucherVO.getPk_voucher() }); // 先从数据库查询当前凭证
			if (varray == null || varray.length == 0) {
				throw new BusinessException("当前单据已被其他人删除，请刷新页面");
			}
			UFDate preparedDate = voucherVO.getPrepareddate(); // 编辑后对的制单日期
			Integer voucherNO = voucherVO.getNo(); // 编辑后的凭证号
			voucherVO = varray[0]; // 用数据库里的数据替换掉编辑的VO，再把编辑后的制单日期和凭证号设置上去
			voucherVO.setPrepareddate(preparedDate);
			voucherVO.setNo(voucherNO);
		}
		// 【双百】2020-11-16：NC63推送过来的凭证只能修改：单据日期、凭证号两个字段【结束】

		voucherVO.setModifier(InvocationInfoProxy.getInstance().getUserId());
		voucherVO.setModifiedtime(new UFDateTime(busidate.toString()));
		return (new VoucherWebBO()).saveVoucher(voucherVO, isAdd, busidate);
	}

	public Map<String, Object> saveError(VoucherWebVO voucherWebVO) throws BusinessException {
		return (new VoucherWebBO()).saveError(voucherWebVO);
	}

	public Map<String, Object> offsetVoucher(String pk_voucher, String offsetType) throws BusinessException {
		if (StringUtil.isEmptyWithTrim(pk_voucher)) {
			return null;
		} else {
			VoucherVO voucher = (new VoucherBO()).queryByPk(pk_voucher);
			VoucherVO offVO = (new OffsetVoucherService()).offsetVoucher(voucher, Integer.valueOf(offsetType));
			VoucherMDVO mdvo = new VoucherMDVO(offVO, true);
			Map<String, Object> transVoucher = (new VoucherWebQryBO()).transVoucher(mdvo);
			return transVoucher;
		}
	}

	public Map<String, Object> deleteVoucher(String[] pk_vouchers) throws BusinessException {

		// 【双百】2020-11-16：NC63推送过来的凭证不允许删除【开始】
		IVoucher service = NCLocator.getInstance().lookup(IVoucher.class);
		VoucherVO[] vouchers = service.queryByPks(pk_vouchers); // 查询所有凭证
		if (vouchers != null && vouchers.length > 0) {
			for (VoucherVO voucher : vouchers) {
				String billno = voucher.getFree3(); // 单据号：单据号不空，说明是否从NC63推送过来的凭证
				if (billno != null && !"".equals(billno.trim())) {
					throw new BusinessException("NC63推送过来的凭证不允许删除");
				}
			}
		} // 【双百】2020-11-16：NC63推送过来的凭证不允许删除【结束】

		return (new VoucherWebBO()).deleteVoucher(pk_vouchers);
	}

	// 【双百】2020-11-26：凭证删除方法（系统原理的删除方法和Rest API删除凭证的方法校验逻辑不一样，所以新加了一个方法）【开始】
	public Map<String, Object> deleteVoucher4RestAPI(String[] pk_vouchers) throws BusinessException {
		return (new VoucherWebBO()).deleteVoucher(pk_vouchers);
	}
	// 【双百】2020-11-26：凭证删除方法（系统原理的删除方法和Rest API删除凭证的方法校验逻辑不一样，所以新加了一个方法）【结束】

	public Map<String, Object> copyVoucher(VoucherVO voucher, String busidate) throws BusinessException {
		return (new VoucherWebBO()).copyVoucher(voucher, busidate);
	}

	public HashMap<String, Object> checkVoucher(String[] pk_vouchers, boolean op, boolean isList)
			throws BusinessException {
		return (new VoucherWebBO()).checkVoucher(pk_vouchers, op, isList);
	}

	@SuppressWarnings("unchecked")
	public HashMap<String, Object> tallyVoucher(String[] pk_vouchers, String date, boolean op, boolean isList)
			throws BusinessException {

		// HashMap<String, Object> returnMap = (new VoucherWebBO()).tallyVoucher(pk_vouchers, date, op, isList); // 标准产品记账
				Map<String, Object> returnMap = new HashMap<String, Object>();
				//根据参数控制NCC凭证是否同步到NC63
				String paraSql = "SELECT value FROM pub_sysinit WHERE initcode  ='GL140' and nvl(dr,0)=0 "; 
				String para = (String) new BaseDAO().executeQuery(paraSql, new ColumnProcessor());
				String paraSqls = "SELECT value FROM pub_sysinit WHERE initcode  ='GL145' and nvl(dr,0)=0 "; 
				String paras = (String) new BaseDAO().executeQuery(paraSqls, new ColumnProcessor());
				if(null != paras && paras.equals("Y")) {
					// 【双百】2020-12-14：记账逻辑修改：标准产品记账的基础上添加推送凭证逻辑-【开始】
					IVoucherRestService service = NCLocator.getInstance().lookup(IVoucherRestService.class);
//					Map<String, Object> returnMap = service.tallyByMultiThread(pk_vouchers, date, op, isList); // 记账、反记账
					returnMap = service.tallyByMultiThread(pk_vouchers, date, op, isList); // 记账、反记账
					// 【双百】2020-12-14：记账逻辑修改：标准产品记账的基础上添加推送凭证逻辑-【结束】
				}else {
					if(null != para && para.equals("Y")) {
						// 【双百】2020-12-14：记账逻辑修改：标准产品记账的基础上添加推送凭证逻辑-【开始】
						IVoucherRestService service = NCLocator.getInstance().lookup(IVoucherRestService.class);
//					Map<String, Object> returnMap = service.tallyByMultiThread(pk_vouchers, date, op, isList); // 记账、反记账
						returnMap = service.tallyByMultiThread(pk_vouchers, date, op, isList); // 记账、反记账
						// 【双百】2020-12-14：记账逻辑修改：标准产品记账的基础上添加推送凭证逻辑-【结束】
					}else {
						returnMap = (new VoucherWebBO()).tallyVoucher(pk_vouchers, date, op, isList); // 标准产品记账
					}
				}

		return (HashMap<String, Object>) returnMap;
	}

	public HashMap<String, Object> abandonVoucher(String[] pk_vouchers, boolean op, boolean isList)
			throws BusinessException {

		// 【双百】2020-12-03：NC63推送过来的凭证不允许作废【开始】
		IVoucher service = NCLocator.getInstance().lookup(IVoucher.class);
		VoucherVO[] vouchers = service.queryByPks(pk_vouchers); // 查询所有凭证
		if (vouchers != null && vouchers.length > 0) {
			for (VoucherVO voucher : vouchers) {
				String billno = voucher.getFree3(); // 单据号：单据号不空，说明是否从NC63推送过来的凭证
				if (billno != null && !"".equals(billno.trim())) {
					throw new BusinessException("NC63推送过来的凭证不允许作废");
				}
			}
		} // 【双百】2020-12-03：NC63推送过来的凭证不允许作废【结束】

		return (new VoucherWebBO()).abandonVoucher(pk_vouchers, op, isList);
	}

	public HashMap<String, Object> signVoucher(String[] pk_vouchers, String date, boolean op, boolean isList,
			String signdateType) throws BusinessException {
		return (new VoucherWebBO()).signVoucher(pk_vouchers, date, op, isList, signdateType);
	}

	public Map<String, Integer> getVoucherNo(VoucherWebVO voucherWebVO) throws BusinessException {
		String pk_accountingbook = voucherWebVO.getPk_accountingbook().getValue();
		String preparedate = voucherWebVO.getPrepareddate().getValue();
		String pk_vouchertype = voucherWebVO.getPk_vouchertype().getValue();
		return (new VoucherWebQryBO()).getVoucherNo(pk_accountingbook, new UFDate(preparedate), pk_vouchertype);
	}

	public VoucherMDVO showSumDetail(String pk_voucher) throws BusinessException {
		return (new VoucherWebBO()).showSumDetail(pk_voucher);
	}

	public Map<String, Object> apportion(VoucherVO voucher, int selectIndex, UFDouble apportionAmount,
			String pk_apprule) throws BusinessException {
		VoucherVO apportion = (new ApportionBO()).apportion(voucher, selectIndex, apportionAmount, pk_apprule);
		VoucherMDVO mdVO = new VoucherMDVO(apportion, true);
		VoucherDetailMDVO[] detailvos = (new VoucherWebQryBO()).catSubjName(mdVO.getDetailMDVOs());
		mdVO.setDetailMDVOs(detailvos);
		Map<String, Object> map = new HashMap();
		map.put("voucher", mdVO);
		Map<String, Object> paraInfo = (new AccountingbookQryBO()).queryBookCombineInfo(mdVO.getPk_accountingbook(),
				mdVO.getPrepareddate().toStdString(), true);
		map.put("paraInfo", paraInfo);
		boolean isShowNum = false;
		VoucherDetailMDVO[] var11 = detailvos;
		int var12 = detailvos.length;

		for (int var13 = 0; var13 < var12; ++var13) {
			VoucherDetailMDVO detail = var11[var13];
			if (detail.getIsShowNum().booleanValue() || !UFDouble.ZERO_DBL.equals(detail.getDebitquantity())
					|| !UFDouble.ZERO_DBL.equals(detail.getCreditquantity())) {
				isShowNum = true;
				break;
			}
		}

		paraInfo.put("isShowNum", isShowNum);
		return map;
	}

	public void exportXML(String[] pk_vouchers, String filepath, boolean fileground) throws BusinessException {
		(new VoucherWebBO()).exportXML(pk_vouchers, filepath, fileground);
	}

	public Map<String, Object> doParallel(VoucherVO voucher, boolean isAuto) throws BusinessException {
		Vector<DetailVO> detailVOs = voucher.getDetail();
		List<DetailVO> details = new ArrayList();
		Iterator var5 = detailVOs.iterator();

		while (true) {
			DetailVO detail;
			do {
				if (!var5.hasNext()) {
					voucher.setDetails((DetailVO[]) details.toArray(new DetailVO[0]));
					OperationResultVO result = (new VoucherPxjz()).doPxjz(voucher, new VoucherVO(), isAuto);
					Map<String, Object> map = new HashMap();
					if (result != null) {
						if (!StringUtil.isEmptyWithTrim(result.m_strDescription)) {
							map.put("error", result.m_strDescription);
						}

						VoucherVO addvoucher = (VoucherVO) result.m_userIdentical;
						if (addvoucher != null && addvoucher.getDetail() != null) {
							details.addAll(addvoucher.getDetail());
						}
					}

					voucher.setDetails((DetailVO[]) details.toArray(new DetailVO[0]));
					VoucherMDVO mdVO = new VoucherMDVO(voucher, true);
					VoucherDetailMDVO[] detailvos = (new VoucherWebQryBO()).catSubjName(mdVO.getDetailMDVOs());
					mdVO.setDetailMDVOs(detailvos);
					map.put("voucher", mdVO);
					Map<String, Object> paraInfo = (new AccountingbookQryBO()).queryBookCombineInfo(
							mdVO.getPk_accountingbook(), mdVO.getPrepareddate().toStdString(), true);
					map.put("paraInfo", paraInfo);
					boolean isShowNum = false;
					VoucherDetailMDVO[] var11 = detailvos;
					int var12 = detailvos.length;

					for (int var13 = 0; var13 < var12; ++var13) {
						VoucherDetailMDVO detailss = var11[var13];
//						VoucherDetailMDVO detail = var11[var13];
						if (detailss.getIsShowNum().booleanValue() || !UFDouble.ZERO_DBL.equals(detailss.getDebitquantity())
								|| !UFDouble.ZERO_DBL.equals(detailss.getCreditquantity())) {
							isShowNum = true;
							break;
						}
					}

					paraInfo.put("isShowNum", isShowNum);
					return map;
				}

				detail = (DetailVO) var5.next();
			} while ((detail.getPk_accasoa() == null || detail.getPk_accasoa().trim().equals(""))
					&& detail.getAssid() == null
					&& (detail.getLocalcreditamount() == null || detail.getLocalcreditamount().doubleValue() == 0.0D)
					&& (detail.getLocaldebitamount() == null || detail.getLocaldebitamount().doubleValue() == 0.0D)
					&& (detail.getDebitamount() == null || detail.getDebitamount().doubleValue() == 0.0D)
					&& (detail.getCreditamount() == null || detail.getCreditamount().doubleValue() == 0.0D)
					&& (detail.getDebitquantity() == null || detail.getDebitquantity().doubleValue() == 0.0D)
					&& (detail.getCreditquantity() == null || detail.getCreditquantity().doubleValue() == 0.0D));

			details.add(detail);
		}
	}

	public Map<String, Object> botCreatVoucher(Map<String, Object> params) throws BusinessException {
		return (new BotCreateVouhcerBO()).botCreatVoucher(params);
	}

	public Map<String, Object> queryAccbookInfo(Map<String, Object> params) throws BusinessException {
		String companyPK = (String) ((Map) params.get("companychoose")).get("pk_org");
		String pk_accountingbook = AccountRepUtil.getAccountingbookPKByOrgPK(companyPK);
		AccountingBookVO vo = AccountBookUtil.getAccountingBookVOByPrimaryKey(pk_accountingbook);
		Map<String, Object> result = new HashMap(2);
		if (vo != null) {
			result.put("refpk", vo.getPk_accountingbook());
			result.put("refname", GLMultiLangUtil.getMultiName(vo));
		}

		return result;
	}
}