package com.huigou.topsun.sap.acceptanceFormAck.application.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.huigou.topsun.sap.acceptanceFormAck.application.SapAcceptanceFormAckApplication;
import com.huigou.topsun.sap.acceptanceFormAck.domain.SapAcceptanceFormAck;
import com.huigou.topsun.sap.common.HttpClient;
import com.huigou.util.JSONUtil;
import com.huigou.util.SDO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
@author YourUserName
*/
@Service
@RequiredArgsConstructor
public class SapAcceptanceFormAckApplicationImpl  implements SapAcceptanceFormAckApplication  {

	private final ObjectMapper objectMapper;

	private final HttpClient httpClient;

	@PersistenceContext(unitName = "system")
	private EntityManager entityManager;

	@Override
	public ArrayList<Map<String, Object>> findAcceptanceForm(SDO sdo) {
		String execute;
		Map<String, Object> param = sdo.getProperties();

		Set<Object> criteriaParam = setCriteria(param);
		String url = "query_dn_mark/query_dn_mark";
		List<SapAcceptanceFormAck> acceptanceForms = null;
		try {
			execute = httpClient.execute(criteriaParam, url);
			//忽略不存在
			objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
			//忽略大小写
			objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
			acceptanceForms = objectMapper.readValue(execute, new TypeReference<List<SapAcceptanceFormAck>>() {});
		} catch (JsonProcessingException e) {
			e.printStackTrace();
			return null;
		} catch (RuntimeException | IOException e ) {
			throw new RuntimeException(e);
		}
		return objectMapper.convertValue(acceptanceForms, new TypeReference<ArrayList<Map<String, Object>>>() {
		});
	}

//			execute = TestClientHttp.execute(param, "http://127.0.0.1:8080/topsun_xt_war/sapAcceptanceForm/queryAcceptanceForm.ajax");
//			String resultStr = JSONObject.parseObject(execute).get("data").toString();

	public Set<Object> setCriteria(Map<String, Object> param) {
		param.remove("pagesize");
		param.remove("page");
		param.remove("sortfields");

		Map<String, Object> vbeln = new HashMap<>(3);
		vbeln.put("VBELN_LOW", param.get("vbeln_low"));
		param.remove("vbeln_low");
		param.remove("vbeln_high");
		//vbeln.put("VBELN_HIGH", param.get("vbeln_high"));
		param.put("vbeln", new Object[] { vbeln });

		Map<String, Object> bstnk = new HashMap<>(3);
		bstnk.put("BSTNK_LOW", param.get("bstnk_low"));
		param.remove("bstnk_low");
		param.remove("bstnk_high");
		//bstnk.put("BSTNK_HIGH", param.get("bstnk_high"));
		param.put("bstnk", new Object[] { bstnk });

		Map<String, Object> zsckdt = new HashMap<>(3);
		zsckdt.put("ZSCKDT_LOW", param.get("zsckdt_low"));
		param.remove("zsckdt_low");
		param.remove("zsckdt_high");
		//zsckdt.put("ZSCKDT_HIGH", param.get("zsckdt_high"));
		param.put("zsckdt", new Object[] { zsckdt });

		Map<String, Object> lfdat = new HashMap<>(3);
		lfdat.put("LFDAT_LOW", param.get("lfdat_low"));
		param.remove("lfdat_low");
		param.remove("lfdat_high");
		//lfdat.put("LFDAT_HIGH", param.get("lfdat_high"));
		param.put("lfdat", new Object[] { lfdat });

		Map<String, Object> zinstnum = new HashMap<>(3);
		zinstnum.put("ZINSTNUM_LOW", param.get("zinstnum_low"));
		param.remove("zinstnum_low");
		param.remove("zinstnum_high");
		//zinstnum.put("ZINSTNUM_HIGH", param.get("zinstnum_high"));
		param.put("zinstnum", new Object[] { zinstnum });

		Map<String, Object> upperCaseMap = param.entrySet().stream()
				.collect(Collectors.toMap(
						entry -> entry.getKey().toUpperCase(),
						Map.Entry::getValue
				));

		Set<Object> set = new HashSet<>();
		set.add(upperCaseMap);
		return set;
	}

	@Override
	public String ackAcceptanceForm(SDO sdo) {
		String url = "updat_ztfifmda/updat_ztfifmda";
		String string = sdo.getString("params");
		String execute;
		try {
			execute = httpClient.execute(string, url);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
		List<Object> list = JSONUtil.toList(execute);
		Object o = list.get(0);
		Map<String, Object> map = BeanUtil.beanToMap(o);
		String message = (String)map.get("MESSAGE");
		return message;
	}

	/**
	 * @description 模拟 SAP 接口 (临时)
	 * @param acceptanceForm 查询条件
	 * @return java.lang.String
	 * @author qinzhenguan
	 * @createDate 2024/1/23 11:50
	 */
	@Override
	public String queryAcceptanceForms(SapAcceptanceFormAck acceptanceForm) throws JsonProcessingException {

		CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
		CriteriaQuery<SapAcceptanceFormAck> query = criteriaBuilder.createQuery(SapAcceptanceFormAck.class);

		Root<SapAcceptanceFormAck> root = query.from(SapAcceptanceFormAck.class);
		List<Predicate> predicates = new ArrayList<>();

		// ======================  设置查询条件  ======================
		settingCriteriaAck(acceptanceForm, predicates, criteriaBuilder, root);

		query.where(criteriaBuilder.and(predicates.toArray(new Predicate[0])));
		List<SapAcceptanceFormAck> results = entityManager.createQuery(query).getResultList();

		return results.size() > 0 ? objectMapper.writeValueAsString(results) : "";
	}

	/***
	 * @description 设置查询条件
	 * @author qinzhenguan
	 * @createDate 2024/1/24 8:22
	 */
	public void settingCriteriaAck(SapAcceptanceFormAck acceptanceForm, List<Predicate> predicates,
								   CriteriaBuilder criteriaBuilder, Root<SapAcceptanceFormAck> root) {
		if(acceptanceForm.getKunag() != null && !acceptanceForm.getKunag().isEmpty()) {
			predicates.add(criteriaBuilder.equal(root.get("kunag"), acceptanceForm.getKunag()));
		}
		if(acceptanceForm.getVkorg() != null && !acceptanceForm.getVkorg().isEmpty()) {
			predicates.add(criteriaBuilder.equal(root.get("vkorg"), acceptanceForm.getVkorg()));
		}
		if(acceptanceForm.getLfdat() != null) {
			predicates.add(criteriaBuilder.equal(root.get("lfdat"), acceptanceForm.getLfdat()));
		}
	}

}
