package nccloud.impl.org.listener;

import nc.vo.org.OrgVO;
import nc.vo.org.OrgVatVO;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.BusinessException;
import nc.vo.bd.countryzone.CountryZoneVO;
import nc.vo.bd.cust.CustSupplierVO;
import nc.vo.bd.cust.CustomerVO;
import nc.vo.bd.cust.CustvatVO;
import nc.vo.bd.supplier.SupplierVO;
import nc.vo.bd.supplier.SupvatVO;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import nc.hr.utils.InSQLCreator;
import nc.itf.uap.IUAPQueryBS;
import nc.jdbc.framework.SQLParameter;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.pub.billcode.itf.IBillcodeManage;
import nc.pub.billcode.vo.BillCodeContext;
import nc.bs.businessevent.IBusinessEvent;
import nc.bs.dao.BaseDAO;
import nc.bs.framework.common.InvocationInfoProxy;
import nc.bs.framework.common.NCLocator;
import nc.itf.bd.cust.baseinfo.ICustBaseInfoService;
import nc.itf.bd.cust.baseinfo.ICustSupplierService;
import nc.itf.org.IOrgVatQryService;
import nc.bs.businessevent.IBusinessListener;
import nc.bs.businessevent.bd.BDCommonEvent;

/**
 * <b> 业务插件：业务单元自动生成内部客商 </b>
 * 
 * 	业务逻辑完全按照标准产品生成内部客商的代码。没有直接调用标准产品IOrgCreateInnerCustSuppService接口
 * 	是因为，在新增后触发业务插件的时候，插件类中用刚新增的pk_org去查询组织信息时无法查询到数据的情况。
 * 
 * 2020-12-08
 */
public class GenerateInnerCustListener implements IBusinessListener {

	private static final String CUST_ORG = "bgyfw"; // 内部客商组织编码
	private static final String CUST_CLASS = "01"; // 内部客商分类编码
	private static final String SUPPLIER_CLASS = "01"; // 供应商分类编码

	private BaseDAO dao = new BaseDAO();
	private IUAPQueryBS baseQueryService = NCLocator.getInstance().lookup(IUAPQueryBS.class);

	@Override
	@SuppressWarnings("unchecked")
	public void doAction(IBusinessEvent event) throws BusinessException {

		BDCommonEvent businessEvent = (BDCommonEvent) event;
		Object[] objs = businessEvent.getNewObjs();
		if (objs == null || objs.length == 0) {
			return;
		}

		// 1.过滤掉不用自动生成内部客商的VO
		List<OrgVO> vos = new ArrayList<OrgVO>();
		for (int i = 0; i < objs.length; i++) {
			OrgVO vo = (OrgVO) objs[i];
			String def11 = vo.getDef11(); // 所属区域
			if (def11 != null && !"".equals(def11.trim())) {
				vos.add(vo); // 所属区域不空时自动生成内部客商
			}
		}
		if (vos.size() == 0) {
			return;
		}

		// 2.校验：是否可以生成内部客商
		for (OrgVO vo : vos) {
			UFBoolean orgType5 = vo.getOrgtype5(); // 是否勾选财务组织职能
			UFBoolean orgType15 = vo.getOrgtype15(); // 是否勾选利润中心职能
			if (!orgType5.booleanValue() && !orgType15.booleanValue()) {
				// 没有勾选财务职能和利润中心职能的业务单元不能生成内部客商
				throw new BusinessException(
						"业务插件【自动生成内部客商】中出错：业务单元【" + vo.getCode() + "】" + "既没有财务职能也没有利润中心职能，不能自动生成内部客商");
			}
		}

		// 3.校验：是否已生成内部客商
		String[] pks = vos.stream().map(vo -> vo.getPk_org()).toArray(String[]::new);
		String where = "pk_financeorg = (" + new InSQLCreator().getInSQL(pks) + ")";
		Collection<CustSupplierVO> supplierVOs = this.baseQueryService.retrieveByClause(CustSupplierVO.class, where);
		if (supplierVOs != null && supplierVOs.size() > 0) {
			throw new BusinessException("业务插件【自动生成内部客商】中出错：当前业务单元已经生成内部客商，不能重复生成");
		}

		// 4.获取自动生成内部客商需要的一些固定参数
		String pk_org = getOrg(CUST_ORG); // 获取客商所属组织
		String custClass = getCustClass(CUST_CLASS); // 获取客商分类
		String supplierClass = getSupplierClass(SUPPLIER_CLASS); // 获取供应商分类

		ICustBaseInfoService custService = NCLocator.getInstance().lookup(ICustBaseInfoService.class);
		ICustSupplierService supplierService = NCLocator.getInstance().lookup(ICustSupplierService.class);
		for (OrgVO vo : vos) {
			String pk_country = vo.getCountryzone(); // 查询业务单元国家地区
			if (pk_country == null) {
				throw new BusinessException("业务单元【" + vo.getCode() + "】未设置国家地区，无法自动生成内部客商");
			}
			CountryZoneVO countryVO = (CountryZoneVO) baseQueryService.retrieveByPK(CountryZoneVO.class, pk_country);
			OrgVatVO[] orgVatVOs = getVatVOs(vo.getPk_org(), countryVO); // 获取业务单元Vat VO
			// 5.构造客户VO，并新增客户
			CustomerVO customerVO = createCustomerVO(pk_org, custClass, vo, countryVO, orgVatVOs);
			customerVO = custService.insertCustomerVO(customerVO, true); // 保存客商
			// 6.构造供应商VO，并新增供应商
			SupplierVO supplierVO = createSupplierVO(pk_org, supplierClass, vo, countryVO, orgVatVOs);
			supplierService.insertSupAndRelaToCust(supplierVO, customerVO);
		}
	}

	/**
	 * 获取客户分类主键
	 * 
	 * @param code
	 * @return
	 * @throws BusinessException
	 */
	public String getCustClass(String code) throws BusinessException {
		String sql = "select t.pk_custclass from bd_custclass t where t.code = ?";
		SQLParameter params = new SQLParameter();
		params.addParam(code);
		Object res = this.dao.executeQuery(sql, params, new ColumnProcessor());
		if (res == null) {
			throw new BusinessException("业务插件【自动生成内部客商】中出错：系统中不存在编码为【" + code + "】的客商分类");
		}
		return res.toString();
	}

	/**
	 * 获取供应商分类主键
	 * 
	 * @param code
	 * @return
	 * @throws BusinessException
	 */
	public String getSupplierClass(String code) throws BusinessException {
		String sql = "select t.pk_supplierclass from bd_supplierclass t where t.code = ?";
		SQLParameter params = new SQLParameter();
		params.addParam(code);
		Object res = this.dao.executeQuery(sql, params, new ColumnProcessor());
		if (res == null) {
			throw new BusinessException("业务插件【自动生成内部客商】中出错：系统中不存在编码为【" + code + "】的供应商分类");
		}
		return res.toString();
	}

	/**
	 * 获取组织主键
	 * 
	 * @param code
	 * @return
	 * @throws BusinessException
	 */
	public String getOrg(String code) throws BusinessException {
		String sql = "select t.pk_org from org_orgs t where t.code = ?";
		SQLParameter params = new SQLParameter();
		params.addParam(code);
		Object res = this.dao.executeQuery(sql, params, new ColumnProcessor());
		if (res == null) {
			throw new BusinessException("业务插件【自动生成内部客商】中出错：系统中不存在编码为【" + code + "】的组织");
		}
		return res.toString();
	}

	/**
	 * 获取业务单元Vat VO
	 * 
	 * @param pk_org
	 * @param countryVO
	 * @return
	 * @throws BusinessException
	 */
	public OrgVatVO[] getVatVOs(String pk_org, CountryZoneVO countryVO) throws BusinessException {

		if (pk_org == null || countryVO == null) {
			return null;
		}

		IOrgVatQryService service = NCLocator.getInstance().lookup(IOrgVatQryService.class);
		return service.queryOrgVatVOsByGroupIDAndOrgId(null, pk_org);
	}

	/**
	 * 构造客商VO
	 * 
	 * @param pk_org
	 * @param pk_custclass
	 * @param orgVO
	 * @param countryVO
	 * @param orgVatVOs
	 * @return
	 * @throws BusinessException
	 */
	public CustomerVO createCustomerVO(String pk_org, String pk_custclass, OrgVO orgVO, CountryZoneVO countryVO,
			OrgVatVO[] orgVatVOs) throws BusinessException {
		if (pk_org == null || pk_custclass == null || orgVO == null || countryVO == null) {
			throw new BusinessException("构造客户VO参数错误");
		}
		String pk_group = InvocationInfoProxy.getInstance().getGroupId();
		CustomerVO vo = new CustomerVO();
		vo.setStatus(2);

		vo.setPk_group(pk_group);
		vo.setPk_org(pk_org);
		vo.setCode(orgVO.getCode());
		vo.setShortname(null);
		vo.setName(orgVO.getName());
		vo.setName2(orgVO.getName2());
		vo.setName3(orgVO.getName3());
		vo.setName4(orgVO.getName4());
		vo.setName5(orgVO.getName5());
		vo.setName6(orgVO.getName6());
		vo.setPk_custclass(pk_custclass);
		vo.setCustprop(Integer.valueOf(1));
		vo.setPk_financeorg(orgVO.getPk_org());
		vo.setEnablestate(Integer.valueOf(2));
		vo.setIsfreecust(UFBoolean.FALSE);
		vo.setFrozenflag(UFBoolean.FALSE);
		vo.setIssupplier(UFBoolean.FALSE);

		vo.setCustvat(getCustVatVOs(orgVatVOs, countryVO.getPk_country())); // 客户Vat
		vo.setVatcode((orgVatVOs == null || orgVatVOs.length == 0) ? "" : orgVatVOs[0].getVatcode());

		vo.setPk_country(countryVO.getPrimaryKey());
		vo.setPk_timezone(countryVO.getPk_timezone());
		vo.setPk_format(countryVO.getPk_format());
		return vo;
	}

	/**
	 * 获取客户VAT
	 * 
	 * @param orgVatVOs
	 * @param pk_country
	 * @return
	 * @throws BusinessException
	 */
	private CustvatVO[] getCustVatVOs(OrgVatVO[] orgVatVOs, String pk_country) throws BusinessException {
		if (orgVatVOs == null || orgVatVOs.length == 0) {
			return null;
		}

		List<CustvatVO> custVatVOs = new ArrayList<CustvatVO>();
		for (int i = 0; i < orgVatVOs.length; i++) {
			if (!pk_country.equals(orgVatVOs[i].getPk_country())) {
				CustvatVO custVatVO = new CustvatVO();
				custVatVO.setStatus(2);
				custVatVO.setPk_country(orgVatVOs[i].getPk_country());
				custVatVO.setVatcode(orgVatVOs[i].getVatcode());
				custVatVO.setIsvat(UFBoolean.TRUE);
				custVatVO.setDataoriginflag(Integer.valueOf(0));
				custVatVOs.add(custVatVO);
			}
		}
		return custVatVOs.size() == 0 ? null : custVatVOs.toArray(new CustvatVO[0]);
	}

	/**
	 * 构造供应商VO
	 * 
	 * @param pk_org
	 * @param pk_suppclass
	 * @param orgVO
	 * @param countryVO
	 * @param orgVatVOs
	 * @return
	 * @throws BusinessException
	 */
	private SupplierVO createSupplierVO(String pk_org, String pk_suppclass, OrgVO orgVO, CountryZoneVO countryVO,
			OrgVatVO[] orgVatVOs) throws BusinessException {
		if (pk_org == null || pk_suppclass == null || orgVO == null || countryVO == null) {
			throw new BusinessException("构造供应商VO参数错误");
		}
		String pk_group = InvocationInfoProxy.getInstance().getGroupId();
		SupplierVO suppliervo = new SupplierVO();
		suppliervo.setStatus(2);
		suppliervo.setPk_group(pk_group);
		suppliervo.setPk_org(pk_org);
		String precode = getSupplierPreAutoCode(pk_group, pk_org);
		suppliervo.setCode(precode == null ? orgVO.getCode() : precode);
		suppliervo.setShortname(null);
		suppliervo.setName(orgVO.getName());
		suppliervo.setName2(orgVO.getName2());
		suppliervo.setName3(orgVO.getName3());
		suppliervo.setName4(orgVO.getName4());
		suppliervo.setName5(orgVO.getName5());
		suppliervo.setName6(orgVO.getName6());
		suppliervo.setPk_oldsupplier("~");
		suppliervo.setPk_supplierclass(pk_suppclass);
		suppliervo.setSupprop(Integer.valueOf(1));
		suppliervo.setPk_financeorg(orgVO.getPk_org());
		suppliervo.setEnablestate(Integer.valueOf(2));
		suppliervo.setIsfreecust(UFBoolean.FALSE);
		suppliervo.setIscustomer(UFBoolean.TRUE);

		suppliervo.setSupvat(getSupVatVOs(orgVatVOs, countryVO.getPk_country()));
		suppliervo.setVatcode((orgVatVOs == null || orgVatVOs.length == 0) ? "" : orgVatVOs[0].getVatcode());

		suppliervo.setPk_country(countryVO.getPrimaryKey());
		suppliervo.setPk_timezone(countryVO.getPk_timezone());
		suppliervo.setPk_format(countryVO.getPk_format());
		return suppliervo;
	}

	/**
	 * 获取前编码
	 * 
	 * @param pk_group
	 * @param pk_org
	 * @return
	 * @throws BusinessException
	 */
	private String getSupplierPreAutoCode(String pk_group, String pk_org) throws BusinessException {
		IBillcodeManage manage = NCLocator.getInstance().lookup(IBillcodeManage.class);
		BillCodeContext billCodeContext = manage.getBillCodeContext("supplier", pk_group, pk_org);
		if (billCodeContext != null && billCodeContext.isPrecode()) {
			return manage.getPreBillCode_RequiresNew("supplier", pk_group, pk_org);
		}
		return null;
	}

	/**
	 * 获取供应商Vat
	 * 
	 * @param orgVatVOs
	 * @param pk_country
	 * @return
	 * @throws BusinessException
	 */
	private SupvatVO[] getSupVatVOs(OrgVatVO[] orgVatVOs, String pk_country) throws BusinessException {

		if (orgVatVOs == null || orgVatVOs.length == 0) {
			return null;
		}

		List<SupvatVO> supVatVOs = new ArrayList<SupvatVO>();
		for (int i = 0; i < orgVatVOs.length; i++) {
			if (!pk_country.equals(orgVatVOs[i].getPk_country())) {
				SupvatVO supvatvo = new SupvatVO();
				supvatvo.setStatus(2);
				supvatvo.setPk_country(orgVatVOs[i].getPk_country());
				supvatvo.setVatcode(orgVatVOs[i].getVatcode());
				supvatvo.setIsvat(UFBoolean.TRUE);
				supvatvo.setDataoriginflag(Integer.valueOf(0));
				supVatVOs.add(supvatvo);
			}
		}
		return supVatVOs.size() == 0 ? null : (SupvatVO[]) supVatVOs.toArray(new SupvatVO[0]);
	}

}
