package org.fouram.service;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.fouram.constants.WebConstants;
import org.fouram.core.base.service.BaseService;
import org.fouram.core.base.service.RequestService;
import org.fouram.core.plugin.weixin.cp.util.WXCpDepartUtil;
import org.fouram.core.util.Tools;
import org.fouram.core.util.UUIDUtil;
import org.fouram.entity.SapOrg;
import org.fouram.entity.SapUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import me.chanjar.weixin.common.error.WxErrorException;

@Service
public class SapOrgService extends BaseService {

	@Autowired
	private RequestService requestService;

	// FOCompany->FOBusinessUnit->FODivision->FODepartment->cust_orgunit4/cust_org4
	private Map<String, String> getOrgMap(HttpHeaders headers, String entityName) throws Exception {
		String url = "https://api15.sapsf.cn/odata/v2/" + entityName + "?$format=json";
		JsonNode node = requestService.getForObject(url, headers);
		Map<String, String> empInfo = Maps.newHashMap();
		if (node != null) {
			Iterator<JsonNode> iterator = node.get("d").get("results").elements();
			while (iterator.hasNext()) {
				JsonNode userNode = iterator.next();
				String externalCode = userNode.get("externalCode").asText().trim();
				String externalName = null;
				if (WebConstants.ORG1.equals(entityName) || WebConstants.ORG2.equals(entityName)
						|| WebConstants.ORG3.equals(entityName)) {
					externalName = userNode.get("name_zh_CN").asText().trim();
				} else {
					externalName = userNode.get("externalName_zh_CN").asText().trim();
				}
				empInfo.put(externalCode, externalName);
			}
		}
		return empInfo;
	}

	public SapOrg selectOne(String parentId, String sapCode, String level) throws Exception {
		SapOrg sapOrg = SapOrg.builder().sapCode(sapCode).parentId(parentId).level(level).build();
		return (SapOrg) findObject("SapOrgMapper.selectOne", sapOrg);
	}

	private String saveOrUpdateSapOrg(String parentId, String sapCode, String sapName, String level) throws Exception {
		SapOrg sapOrg = selectOne(parentId, sapCode, level);
		if (sapOrg != null) {
			sapOrg.setSapName(sapName);
			update("SapOrgMapper.updateSapName", sapOrg);
		} else {
			sapOrg = SapOrg.builder().id(UUIDUtil.get32UUID()).sapCode(sapCode).sapName(sapName).parentId(parentId)
					.level(level).build();
			save("SapOrgMapper.saveOne", sapOrg);
		}
		return sapOrg.getId();
	}

	public List<SapUser> setOrg(List<SapUser> sapUsers) throws Exception {
		HttpHeaders headers = getHttpHeaders();
		Map<String, String> businessUnitMap = getOrgMap(headers, WebConstants.ORG1);
		Map<String, String> divisionMap = getOrgMap(headers, WebConstants.ORG2);
		Map<String, String> departmentMap = getOrgMap(headers, WebConstants.ORG3);
		Map<String, String> orgunit4Map = getOrgMap(headers, WebConstants.ORG4);// cust_orgunit4/cust_org4

		String userIds = "";
		Map<String, SapUser> map = Maps.newHashMap();
		for (SapUser sapUser : sapUsers) {
			userIds += "'" + sapUser.getUserId() + "',";
			map.put(sapUser.getUserId(), sapUser);
		}
		String empUrl = "https://api15.sapsf.cn/odata/v2/EmpJob?$filter=userId in " + userIds + "&$format=json";
		JsonNode node = requestService.getForObject(empUrl, headers);
		if (node != null) {
			Iterator<JsonNode> iterator = node.get("d").get("results").elements();
			while (iterator.hasNext()) {
				JsonNode userNode = iterator.next();
				String userId = userNode.get("userId").asText().trim();
				SapUser sapUser = map.get(userId);
				String businessUnitCode = userNode.get("businessUnit").asText().trim();
				String divisionCode = userNode.get("division").asText().trim();
				String departmentCode = userNode.get("department").asText().trim();
				String orgunit4Code = userNode.get("customString19").asText().trim();
				String firstOrgId = null;
				if (Tools.notEmpty(businessUnitCode)) {
					sapUser.setFirstOrgName(businessUnitMap.get(businessUnitCode));
					firstOrgId = saveOrUpdateSapOrg(WebConstants.TOP_DEPART.toString(), businessUnitCode,
							sapUser.getFirstOrgName(), "1");
					sapUser.setFirstOrgId(firstOrgId);
				}
				String secondOrgId = null;
				if (Tools.notEmpty(divisionCode)) {
					sapUser.setSecondOrgName(divisionMap.get(divisionCode));
					secondOrgId = saveOrUpdateSapOrg(firstOrgId, divisionCode, sapUser.getSecondOrgName(), "2");
					sapUser.setSecondOrgId(secondOrgId);
				}
				String thirdOrgId = null;
				if (Tools.notEmpty(departmentCode)) {
					sapUser.setThirdOrgName(departmentMap.get(departmentCode));
					thirdOrgId = saveOrUpdateSapOrg(secondOrgId, departmentCode, sapUser.getThirdOrgName(), "3");
					sapUser.setThirdOrgId(thirdOrgId);
				}
				String fourthOrgId = null;
				if (Tools.notEmpty(orgunit4Code)) {
					sapUser.setFourthOrgName(orgunit4Map.get(orgunit4Code));
					fourthOrgId = saveOrUpdateSapOrg(thirdOrgId, orgunit4Code, sapUser.getFourthOrgName(), "4");
					sapUser.setFourthOrgId(fourthOrgId);
				}
			}
		}
		return sapUsers;
	}

	public Map<String, Long> updateAllWxDepartId() throws Exception {
		Map<String, Long> result = Maps.newHashMap();
		List<SapOrg> firstOrgs = selectListByParentId(WebConstants.TOP_DEPART.toString());
		List<SapOrg> allOrgs = Lists.newArrayList();
		for (SapOrg firstOrg : firstOrgs) {
			firstOrg.setWxDepartId(getWxDepartId(firstOrg, WebConstants.TOP_DEPART));
			allOrgs.add(firstOrg);
			List<SapOrg> sencodOrgs = selectListByParentId(firstOrg.getId());
			for (SapOrg sencodOrg : sencodOrgs) {
				sencodOrg.setWxDepartId(getWxDepartId(sencodOrg, firstOrg.getWxDepartId()));
				allOrgs.add(sencodOrg);
				List<SapOrg> thirdOrgs = selectListByParentId(sencodOrg.getId());
				for (SapOrg thirdOrg : thirdOrgs) {
					thirdOrg.setWxDepartId(getWxDepartId(thirdOrg, sencodOrg.getWxDepartId()));
					allOrgs.add(thirdOrg);
					List<SapOrg> fourthOrgs = selectListByParentId(thirdOrg.getId());
					for (SapOrg fourthOrg : fourthOrgs) {
						fourthOrg.setWxDepartId(getWxDepartId(fourthOrg, thirdOrg.getWxDepartId()));
						allOrgs.add(fourthOrg);
					}
				}
			}
		}

		for (SapOrg org : allOrgs) {
			updateWxDepartId(org);
			result.put(org.getId(), org.getWxDepartId());
		}
		return result;
	}

	private Long getWxDepartId(SapOrg org, Long parentId) throws WxErrorException {
		return WXCpDepartUtil.createOrUpdate(org.getWxDepartId(), parentId, org.getSapName());
	}

	@SuppressWarnings("unchecked")
	public List<SapOrg> selectListByParentId(String parentId) throws Exception {
		SapOrg org = SapOrg.builder().parentId(parentId).build();
		return toInfoDetails((List<SapOrg>) findList("SapOrgMapper.selectListByParentId", org));
	}

	public void updateWxDepartId(SapOrg org) throws Exception {
		update("SapOrgMapper.updateWxDepartId", org);
	}

	@SuppressWarnings("unchecked")
	public List<SapOrg> selectListByName(String name) throws Exception {
		return toInfoDetails((List<SapOrg>) findList("SapOrgMapper.selectListByName", name));
	}

	public SapOrg selectById(String id) throws Exception {
		return (SapOrg) findObject("SapOrgMapper.selectById", id);
	}

	public SapOrg toInfoDetail(SapOrg sapOrg) throws Exception {
		if (sapOrg != null) {
			sapOrg.setParentDepart(selectById(sapOrg.getParentId()));
		}
		return sapOrg;
	}

	public List<SapOrg> toInfoDetails(List<SapOrg> sapOrgs) throws Exception {
		for (SapOrg sapOrg : sapOrgs) {
			toInfoDetail(sapOrg);
		}
		return sapOrgs;
	}
}
