package nc.bs.ic.base;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import nc.bs.businessevent.IBusinessEvent;
import nc.bs.businessevent.IBusinessListener;
import nc.bs.framework.common.NCLocator;
import nc.bs.pu.event.PUBusinessEvent;
import nc.impl.pubapp.pattern.rule.IRule;
import nc.itf.uap.IUAPQueryBS;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.jdbc.framework.processor.MapListProcessor;
import nc.md.persist.framework.IMDPersistenceQueryService;
import nc.vo.bd.defdoc.DefdocVO;
import nc.vo.pu.m25.entity.InvoiceItemVO;
import nc.vo.pu.m25.entity.InvoiceVO;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;


/**
 * 采购发票保存后校验
 * @author Yaoyu
 * 2023-05-25
 *
 */
public class InvoiceAfterCheckEvent implements IRule<InvoiceVO>{
	
	
	private IUAPQueryBS bs = NCLocator.getInstance().lookup(IUAPQueryBS.class);
	private IMDPersistenceQueryService service = NCLocator.getInstance().lookup(IMDPersistenceQueryService.class);



	@Override
	public void process(InvoiceVO[] vos) {
		try {
			if (vos instanceof InvoiceVO[]) {
				InvoiceVO InvoiceVO = (InvoiceVO) vos[0];
				InvoiceItemVO[] arrInvoiceItemVO = (InvoiceItemVO[]) InvoiceVO.getChildren(InvoiceItemVO.class);
				//参照上游单据的信息和发票信息一致性校验(抬头、税率)
				//发票金额不可超过采购合同/订单金额
				//购买方发票抬头、税号准确性
				Boolean vbdboo = false;
				Boolean idboo = false;
				//来源单据类型
				String csourcetypecode = arrInvoiceItemVO[0].getCsourcetypecode();
				//来源单据主键
				String csourceid = arrInvoiceItemVO[0].getCsourceid();
				List<Map<Object, Object>> listMap = new ArrayList<Map<Object, Object>>();
				//来源单据是采购订单
				if("21".equals(csourcetypecode)) {
					StringBuffer sql = new StringBuffer();
					sql.append("SELECT");
					sql.append(" po_order_b.pk_order_b,");
					sql.append(" po_order_b.norigtaxmny,");
					sql.append(" po_order_b.ntaxrate,");
					sql.append(" po_order_b.nmny,");
					sql.append(" po_order_b.ntax");
					sql.append(" FROM");
					sql.append(" po_order po_order");
					sql.append(" LEFT JOIN po_order_b po_order_b ON po_order.pk_order = po_order_b.pk_order");
					sql.append(" WHERE");
					sql.append(" po_order.pk_order = '"+csourceid+"'");
					sql.append(" and po_order.dr = 0 and po_order_b.dr = 0");
					listMap = (List<Map<Object, Object>>) bs.executeQuery(sql.toString(), new MapListProcessor());                
				}else
				//来源单据是入库单
				if("45".equals(csourcetypecode)) {
					StringBuffer sql = new StringBuffer();
					sql.append("SELECT");
					sql.append(" ic_purchasein_b.cgeneralbid,");
					sql.append(" po_order_b.pk_order_b,");
					sql.append(" po_order_b.norigtaxmny,");
					sql.append(" po_order_b.ntaxrate,");
					sql.append(" po_order_b.nmny,");
					sql.append(" po_order_b.ntax");
					sql.append(" FROM");
					sql.append(" ic_purchasein_h ic_purchasein_h");
					sql.append(" LEFT JOIN ic_purchasein_b ic_purchasein_b ON ic_purchasein_h.cgeneralhid = ic_purchasein_b.cgeneralhid");
					sql.append(" LEFT JOIN po_order_b po_order_b ON ic_purchasein_b.csourcebillbid = po_order_b.pk_order_b");
					sql.append(" WHERE");
					sql.append(" ic_purchasein_h.cgeneralhid = '"+csourceid+"'");
					sql.append(" and ic_purchasein_h.dr = 0 and ic_purchasein_b.dr = 0 and po_order_b.dr = 0");
					listMap = (List<Map<Object, Object>>) bs.executeQuery(sql.toString(), new MapListProcessor());
				}
				//金额
				UFDouble nmny1 = new UFDouble();
				UFDouble nmny2 = new UFDouble();
				//税额
				UFDouble ntax1 = new UFDouble();
				UFDouble ntax2 = new UFDouble();
				//价税合计
				UFDouble norigtaxmny1 = new UFDouble();
				UFDouble norigtaxmny2 = new UFDouble();
				for (Map<Object, Object> map : listMap) {
					 norigtaxmny2 = norigtaxmny2.add(new UFDouble(map.get("norigtaxmny").toString()));
					 nmny2 = nmny2.add(new UFDouble(map.get("nmny").toString()));
					 ntax2 = ntax2.add(new UFDouble(map.get("ntax").toString()));
				}
				for (InvoiceItemVO invoiceItemVO : arrInvoiceItemVO) {
				//没传发票不比较日期、抬头、纳税人识别号、税率
					if(invoiceItemVO.getVbdef20() != null && !"".equals(invoiceItemVO.getVbdef20())) {
						vbdboo = true;
						String[] arrVbdef20 = invoiceItemVO.getVbdef20().split(",");
						for(String Vbdef20 : arrVbdef20) {
							DefdocVO defdocVO = (DefdocVO) service.queryBillOfNCObjectByPKWithDR(DefdocVO.class, Vbdef20, true).getContainmentObject();
							if(defdocVO.getPid() != null) {
								UFDate date = new UFDate(System.currentTimeMillis());
								UFDate date2 = new UFDate(defdocVO.getPid());
								//当年只能报销当年的控制
								if(date.getYear() != date2.getYear()) {
									ExceptionUtils.wrappBusinessException("行:"+invoiceItemVO.getCrowno()+"不能跨年报销发票!");
								}
							}
							//特殊发票不存在抬头与纳税人识别号可不做校验
							if(defdocVO.getName2() != null && !"".equals(defdocVO.getName2())) {
								//比较抬头
								String sql1 = "select name from org_financeorg_v where pk_vid ='"+InvoiceVO.getParent().getAttributeValue("pk_org_v")+"'";
								String orgname = (String) bs.executeQuery(sql1, new ColumnProcessor());
							
								// 使用正则表达式替换中文括号为英文括号
								String orgnames = orgname.replaceAll("（", "(").replaceAll("）", ")");
								String name2 = defdocVO.getName2().replaceAll("（", "(").replaceAll("）", ")");
								//因有的公司是虚拟公司没有抬头，查询name2是否有匹配的抬头，存在使用档案中维护的。
								String docsql = "select mnecode as invoiceTitle from bd_defdoc where pk_defdoclist = (select pk_defdoclist from bd_defdoclist "
										+ "where code = 'kpttys' and dr = 0) and name = '"+orgnames+"' and enablestate = 2 and dr = 0";
								String invoiceTitle = (String) bs.executeQuery(docsql, new ColumnProcessor());
								//存在使用维护抬头
								if(invoiceTitle != null) {
									orgnames = invoiceTitle;
								}								
								if(!orgnames.equals(name2)) {
									ExceptionUtils.wrappBusinessException("发票抬头与财务组织不一致，请修改财务组织!");
								}
								//比较纳税人识别号
								StringBuffer sql2 = new StringBuffer();
								sql2.append("SELECT");
								sql2.append(" name");
								sql2.append(" FROM");
								sql2.append(" bd_defdoc ");
								sql2.append(" WHERE");
								sql2.append(" pk_defdoclist = ( SELECT pk_defdoclist FROM bd_defdoclist WHERE code = 'CORPYS04' ) ");
								sql2.append(" AND memo = '"+name2+"' ");
								sql2.append(" AND enablestate = 2");
								String tcode = (String) bs.executeQuery(sql2.toString(), new ColumnProcessor());
								String mnecode = defdocVO.getMnecode() == null ? "" : defdocVO.getMnecode();
								if(!mnecode.equals(tcode)) {
									ExceptionUtils.wrappBusinessException("行:"+invoiceItemVO.getCrowno()+"纳税人识别号不正确! 请检查发票纳税人识别号和自定义档案是否正确!");
								}
							}
						}
						for (Map<Object, Object> map : listMap) {
							//只有有上游订单的比较税率
							if(invoiceItemVO.getCsourcebid() != null) {
								idboo = true;
								if (invoiceItemVO.getCsourcebid().equals(map.get("pk_order_b")) || invoiceItemVO.getCsourcebid().equals(map.get("cgeneralbid"))) { 
									//比较税率
									UFDouble ntaxrate1 = invoiceItemVO.getNtaxrate();
									UFDouble ntaxrate2 = new UFDouble(map.get("ntaxrate").toString());
									if(ntaxrate1.compareTo(ntaxrate2) != 0) {
										ExceptionUtils.wrappBusinessException("行:"+invoiceItemVO.getCrowno()+"与采购订单税率不同!");
									}
								}
							}
						}
					}
					norigtaxmny1 = norigtaxmny1.add(invoiceItemVO.getNorigtaxmny());
					nmny1 = nmny1.add(invoiceItemVO.getNmny());
					ntax1 = ntax1.add(invoiceItemVO.getNtax());
				}
				//没有使用ocr，并且没有上游不比较金额
				if(vbdboo && idboo) {
					//比较金额
					if(nmny1.compareTo(nmny2) == 1) {
						ExceptionUtils.wrappBusinessException("不可超过采购订单金额!");
					}
					//比较税额
					if(ntax1.compareTo(ntax2) == 1) {
						ExceptionUtils.wrappBusinessException("不可超过采购订单税额!");
					}
					//比较价税合计							 
					if(norigtaxmny1.compareTo(norigtaxmny2) == 1) {
						ExceptionUtils.wrappBusinessException("不可超过采购订单价税合计金额!");
					}
				}
			}
			
		} catch (Exception e) {
			ExceptionUtils.wrappBusinessException(""+e.getMessage());
		}
	}
}