package nc.api.arap.resource;

import com.google.gson.Gson;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import nc.api.arap.util.ArapAPIUtil;
import nc.bs.framework.common.NCLocator;
import nc.itf.arap.pub.IArapBillService;
import nc.vo.arap.basebill.BaseAggVO;
import nc.vo.arap.openapi.ArapBillOpenApiVO;
import nc.vo.arap.openapi.ArapF0EstiOpenApiVO;
import nc.vo.arap.openapi.ArapF1EstiOpenApiVO;
import nc.vo.arap.verify.ArapVerifyVO;
import nc.vo.ml.NCLangRes4VoTransl;
import nc.vo.pub.BusinessException;
import nc.vo.pub.lang.UFBoolean;
import nccloud.api.rest.utils.NCCRestUtils;
import nccloud.api.rest.utils.ResultMessageUtil;
import nccloud.impl.platform.common.util.StringUtils;
import nccloud.pubitf.arap.openapi.IARAPOpenAPIService;
import nccloud.pubitf.arap.openapi.IBillOpenService;
import nccloud.ws.rest.resource.AbstractNCCRestResource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.json.JSONString;
import java.lang.reflect.Method;
import nc.bs.logging.Logger;
import nc.itf.arap.fieldmap.IBillFieldGet;
import nc.vo.pub.BusinessRuntimeException;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFDouble;
import com.google.gson.internal.LinkedTreeMap;

public class ArapBaseRestResource extends AbstractNCCRestResource {
	public String getModule() {
		return "arap";
	}

	protected <T> T fromJson(String json, Type clazz) {
		return (T) (new Gson()).fromJson(json, clazz);
	}

	public BaseAggVO fromJsonToAggVO(String json, String billtype) {
		ArapBillOpenApiVO apivo = (ArapBillOpenApiVO) fromJson(json, ArapBillOpenApiVO.class);
		return apivo.toAggVO(billtype);
	}

	public ArapF1EstiOpenApiVO fromJsonToAggVOForSP(String json, String billtype) {
		return (ArapF1EstiOpenApiVO) fromJson(json, ArapF1EstiOpenApiVO.class);
	}

	public ArapF0EstiOpenApiVO fromJsonToF0AggVOForSP(String json, String billtype) {
		return (ArapF0EstiOpenApiVO) fromJson(json, ArapF0EstiOpenApiVO.class);
	}

	public ArapVerifyVO fromJsonToArapVerifyVO(String json) {
		return (ArapVerifyVO) fromJson(json, ArapVerifyVO.class);
	}

	public JSONString unCommitAndDelBill(JSONString str, String keyItem, String pk_billtype) throws BusinessException {
		NCCRestUtils.initInvocationInfo();
		String json = str.toJSONString();
		Map<String, String> billMap = (Map) fromJson(json, Map.class);
		String[] pk_bills = null;
		IBillOpenService service = (IBillOpenService) NCLocator.getInstance()
				.lookup(ArapAPIUtil.getClassName(pk_billtype));
		if (StringUtils.isEmpty((String) billMap.get(keyItem))) {
			try {
				List<String> returnMap = service.getPkBySrc(billMap);
				if (returnMap == null) {
					return ResultMessageUtil.exceptionToJSON(
							NCLangRes4VoTransl.getNCLangRes().getStrByID("2006pub_0", "02006pub-0970"), "filed");
				}

				pk_bills = (String[]) returnMap.toArray(new String[returnMap.size()]);
			} catch (Exception e) {
				return ResultMessageUtil.exceptionToJSON(e);
			}
		} else {
			String pk_bill = (String) billMap.get(keyItem);
			pk_bills = pk_bill.split(",");
		}

		try {
			UFBoolean[] checkHasFlowBills = new UFBoolean[0];
			IArapBillService sservice = (IArapBillService) NCLocator.getInstance().lookup(IArapBillService.class);
			checkHasFlowBills = sservice.checkHasFlowBills(pk_bills, pk_billtype);
			if (!ArrayUtils.isEmpty(checkHasFlowBills) && checkHasFlowBills[0].booleanValue()) {
				String mess = NCLangRes4VoTransl.getNCLangRes().getStrByID("2006pub_0", "02006pub-1680");
				throw new BusinessException(mess);
			}

			Map<String, Object> returnMap = service.unCommitAndDelBill(pk_bills);
			if (returnMap == null) {
				return ResultMessageUtil.exceptionToJSON(
						NCLangRes4VoTransl.getNCLangRes().getStrByID("2006pub_0", "02006pub-0970"), "filed");
			}

			return ResultMessageUtil.toJSON(returnMap);
		} catch (Exception e) {
			throw new BusinessException(e);
		}
	}

	protected JSONString queryBill(JSONString str, String pk_billtype) {
		NCCRestUtils.initInvocationInfo();
		String json = str.toJSONString();
		Map<String, String> conditionMap = (Map) fromJson(json, Map.class);
		try {
			IBillOpenService service = (IBillOpenService) NCLocator.getInstance()
					.lookup(ArapAPIUtil.getClassName(pk_billtype));
			List<Map<String, Object>> bills = service.queryBill(conditionMap);
			if (CollectionUtils.isEmpty(bills)) {
				bills = new ArrayList<Map<String, Object>>();
			}
			return ResultMessageUtil.toJSON(bills);
		} catch (Exception e) {
			return ResultMessageUtil.exceptionToJSON(e);
		}
	}

	protected JSONString updateBill(JSONString str, String pk_billtype) {
		NCCRestUtils.initInvocationInfo();
		String json = str.toJSONString();
		Map<String, Object> billMap = (Map) fromJson(json, Map.class);

		try {
			IBillOpenService service = (IBillOpenService) NCLocator.getInstance()
					.lookup(ArapAPIUtil.getClassName(pk_billtype));
			Map<String, String> returnMap = service.updateBill(billMap);
			return ResultMessageUtil.toJSON(returnMap);
		} catch (Exception e) {
			return ResultMessageUtil.exceptionToJSON(e);
		}
	}

	public JSONString deleteBill(JSONString str, String keyItem, String pk_billtype) throws BusinessException {
		NCCRestUtils.initInvocationInfo();
		String json = str.toJSONString();
		Map<String, String> billMap = (Map) fromJson(json, Map.class);
		String[] pk_bills = null;
		if (StringUtils.isEmpty((String) billMap.get(keyItem))) {
			try {
				IBillOpenService service = (IBillOpenService) NCLocator.getInstance()
						.lookup(ArapAPIUtil.getClassName(pk_billtype));
				List<String> returnMap = service.getPkBySrc(billMap);
				if (returnMap == null) {
					return ResultMessageUtil.exceptionToJSON(
							NCLangRes4VoTransl.getNCLangRes().getStrByID("2006pub_0", "02006pub-0970"), "filed");
				}

				pk_bills = (String[]) returnMap.toArray(new String[returnMap.size()]);
			} catch (Exception e) {
				return ResultMessageUtil.exceptionToJSON(e);
			}
		} else {
			String pk_recbill = (String) billMap.get(keyItem);
			pk_bills = pk_recbill.split(",");
		}

		try {
			IArapBillService service = (IArapBillService) NCLocator.getInstance().lookup(IArapBillService.class);
			BaseAggVO[] bills = service.queryArapBillByPKs(pk_bills, pk_billtype);
			if (ArrayUtils.isEmpty(bills)) {
				return ResultMessageUtil.exceptionToJSON(
						NCLangRes4VoTransl.getNCLangRes().getStrByID("2006pub_0", "02006pub-0970"), "filed");
			}

			for (BaseAggVO aggVo : bills) {
				aggVo.getParentVO().setAttributeValue("operate", "API");
			}
			((IARAPOpenAPIService) NCLocator.getInstance().lookup(IARAPOpenAPIService.class)).executeBatchPM("DELETE",
					bills);
			Map<String, String> returnMap = new HashMap<String, String>();
			returnMap.put("successful", "Y");
			return ResultMessageUtil.toJSON(returnMap);
		} catch (Exception e) {
			return ResultMessageUtil.exceptionToJSON(e);
		}
	}

	protected JSONString isclose(Map<String, String> conditionMap, String moduleID) {
		if (conditionMap == null || conditionMap.size() == 0) {
			return null;
		}
		NCCRestUtils.initInvocationInfo();

		try {
			Map<String, String> res = ((IARAPOpenAPIService) NCLocator.getInstance().lookup(IARAPOpenAPIService.class))
					.queryIscloseOrIsendaccStatus(conditionMap, moduleID);
			return ResultMessageUtil.toJSON(res);
		} catch (Exception e) {
			return ResultMessageUtil.exceptionToJSON(e);
		}
	}

	protected JSONString commitBill(JSONString str, String keyItem, String pk_billtype) throws BusinessException {
		return commitUnCommitBill(str, keyItem, pk_billtype, "COMMIT");
	}

	protected JSONString unCommitBill(JSONString str, String keyItem, String pk_billtype) throws BusinessException {
		return commitUnCommitBill(str, keyItem, pk_billtype, "UNCOMMIT");
	}

	private JSONString commitUnCommitBill(JSONString str, String keyItem, String pk_billtype, String actioncode) {
		NCCRestUtils.initInvocationInfo();
		String json = str.toJSONString();
		Map<String, String> billMap = (Map) fromJson(json, Map.class);
		String[] pk_bills = null;
		if (StringUtils.isEmpty((String) billMap.get(keyItem))) {
			try {
				List<String> returnMap = ((IBillOpenService) NCLocator.getInstance().lookup(IBillOpenService.class))
						.getPkBySrc(billMap);

				if (returnMap == null) {
					return ResultMessageUtil.exceptionToJSON(
							NCLangRes4VoTransl.getNCLangRes().getStrByID("2006pub_0", "02006pub-0970"), "filed");
				}
				pk_bills = (String[]) returnMap.toArray(new String[returnMap.size()]);
			} catch (Exception e) {
				return ResultMessageUtil.exceptionToJSON(e);
			}
		} else {
			String pk_bill = (String) billMap.get(keyItem);
			pk_bills = pk_bill.split(",");
		}
		try {
			Map<String, Object> returnMap = ((IARAPOpenAPIService) NCLocator.getInstance()
					.lookup(IARAPOpenAPIService.class)).doBatchCommit(pk_bills, pk_billtype, actioncode);
			if (Integer.parseInt(returnMap.get("failNum").toString()) == 0) {
				return ResultMessageUtil.toJSON(returnMap.get("message"));
			}
			if (Integer.parseInt(returnMap.get("successNum").toString()) == 0) {
				return ResultMessageUtil.exceptionToJSON((String) returnMap.get("message"), "false");
			}
			return ResultMessageUtil.toJSON(returnMap.get("message"));
		} catch (Exception e) {
			return ResultMessageUtil.exceptionToJSON(e);
		}
	}

	/**
	 * 转换Map为VO
	 */
	public static Object fromJsonToVO(Map<?, ?> map, Type t) {
		Object obj = null;
		Class<?> clazz = (Class<?>) t;
		try {
			obj = clazz.newInstance();
			Method[] methods = clazz.getMethods();
			if (methods != null) {
				for (Method method : methods) {
					if (method.getName().startsWith("set")) {// set方法
						String key = (method.getName().replace("set", "")).toLowerCase();
						Object value = map.get(key);
						// 说明文档里。收款银行账户，付款银行账户字段拼接了ap或ar，导致此处可能获取不到值
						if (value == null && (IBillFieldGet.PAYACCOUNT.equals(key)
								|| IBillFieldGet.RECACCOUNT.equals(key) || IBillFieldGet.PK_PAYTERM.equals(key))) {
							List<LinkedTreeMap<String, Object>> link = (List<LinkedTreeMap<String, Object>>) map
									.get("items");
							if (CollectionUtils.isEmpty(link)) {
								String oldkey = key;
								key = "ap_" + key;
								if (map.get(key) == null) {
									key = "ar_" + oldkey;
								}
								value = map.get(key);
							} else {
								LinkedTreeMap<String, Object> linkedMap = link.get(0);
								String oldkey = key;
								key = "ap_" + key;
								if (linkedMap.get(key) == null) {
									key = "ar_" + oldkey;
								}
								value = linkedMap.get(key);
							}

						}
						if (value == null || StringUtils.isEmpty(value.toString()))
							continue;

						Class<?>[] parameterTypes = method.getParameterTypes();
						if (IBillFieldGet.PREPAY.equals(key)) {
							method.invoke(obj,
									(nc.vo.ml.NCLangRes4VoTransl.getNCLangRes().getStrByID("2006pub_0", "02006pub-0997")
											/* @res "预付款" */.equals(value)
											|| nc.vo.ml.NCLangRes4VoTransl.getNCLangRes()
													.getStrByID("2006pub_0", "02006pub-0388")
													/* @res "预收款" */.equals(value)) ? 1 : 0);
						} else if (parameterTypes[0] == UFBoolean.class) {
							method.invoke(obj, UFBoolean.valueOf(value.toString()));
						} else if (parameterTypes[0] == UFDouble.class) {
							method.invoke(obj, new UFDouble(value.toString()));
						} else if (parameterTypes[0] == Integer.class) {
							method.invoke(obj, new Integer(value.toString()));
						} else if (parameterTypes[0] == UFDate.class) {
							method.invoke(obj, new UFDate(value.toString()));
						} else {
							method.invoke(obj, value);
						}
					}
				}
			}
		} catch (Exception e) {
			Logger.error(e.getMessage(), e);
			throw new BusinessRuntimeException(e.getMessage());
		}
		return obj;
	}

}
