package nckd.jimin.jyyy.hr.haos.util;

import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.orm.query.QFilter;
import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class OrgUtils {

    static QFilter isNotCurrent = new QFilter("iscurrentversion", "=", '0');
    static QFilter isCurrent = new QFilter("iscurrentversion", "=", "1");
    static QFilter dataStatusFilter = new QFilter("datastatus", "in", Arrays.asList("1", "2"));
    static QFilter dataStatusCurrent = new QFilter("datastatus", "in", Arrays.asList("-3", "0"));
    static QFilter enableFilter = new QFilter("enable", "=", "1");
    static QFilter initStatusFilter = new QFilter("initstatus", "=", "2");

    /**
     * 获取组织结构编码Map
     * key = structnumber， value = Map包含number和name
     * @param structNumberSet
     * @param modifyTime
     * @return
     */
    public static Map<String, Map<String, String>> getStructNumberMap(Set<String> structNumberSet, Date modifyTime) {
        HRBaseServiceHelper adminOrg = new HRBaseServiceHelper("haos_adminorgdetail");
        QFilter structNumberFilter = new QFilter("structnumber", "in", structNumberSet);
        if (Objects.isNull(modifyTime)) {
            structNumberFilter.and(isCurrent);
        } else {
            QFilter effDateFilter = (new QFilter("bsed", "<=", modifyTime)).and(new QFilter("bsled", ">=", modifyTime));
            structNumberFilter.and(isNotCurrent).and(effDateFilter);
        }

        DynamicObject[] adminOrgNumber = adminOrg.query("id,structnumber,name,number", new QFilter[]{structNumberFilter, dataStatusFilter, initStatusFilter});
        Stream<DynamicObject> dynamicObjectStream = Arrays.stream(adminOrgNumber).filter(distinctByKey1((s) -> {
            return s.getString("structnumber");
        }));
        Map<String, Map<String, String>> stringStringMap = (Map)dynamicObjectStream.collect(Collectors.toMap((dy) -> {
            return (String)Optional.ofNullable(dy.getString("structnumber")).orElse("");
        }, (dy) -> {
            Map map = new HashMap<>();
            map.put("number",(String)Optional.ofNullable(dy.getString("number")).orElse(""));
            map.put("name",(String)Optional.ofNullable(dy.getString("name")).orElse(""));
            return map;
        }));
        structNumberSet.removeAll(stringStringMap.keySet());
        if (structNumberSet.size() == 0) {
            return stringStringMap;
        } else {
            structNumberFilter = new QFilter("structnumber", "in", structNumberSet);
            DynamicObject[] adminOrgNumberNot = adminOrg.query("id,structnumber,name,number", new QFilter[]{structNumberFilter, isCurrent, dataStatusCurrent, enableFilter, initStatusFilter});
            dynamicObjectStream = Arrays.stream(adminOrgNumberNot).filter(distinctByKey1((s) -> {
                return s.getString("structnumber");
            }));
            Map<String, Map<String, String>> stringStringMapNot = (Map)dynamicObjectStream.collect(Collectors.toMap((dy) -> {
                return (String)Optional.ofNullable(dy.getString("structnumber")).orElse("");
            }, (dy) -> {
                Map map = new HashMap<>();
                map.put("number",(String)Optional.ofNullable(dy.getString("number")).orElse(""));
                map.put("name",(String)Optional.ofNullable(dy.getString("name")).orElse(""));
                return map;
            }));
            stringStringMap.putAll(stringStringMapNot);
            return stringStringMap;
        }
    }

    /**
     * 根据组织的structlongnumber处理组织的长名称和长编码
     * @param org
     * @param structMap
     */
    public static void dealLongNameAndNumber(DynamicObject org, Map<String, Map<String, String>> structMap) {
        String structLongNumber = org.getString("structlongnumber");
        String[] structNumbers =  structLongNumber.split("!");
        String[] longNames = new String[structNumbers.length];
        String[] longNumbers = new String[structNumbers.length];
        for(int i = 0; i<structNumbers.length; i++) {
            if(structMap.containsKey(structNumbers[i])) {
                longNames[i] = structMap.get(structNumbers[i]).get("name");
                longNumbers[i] = structMap.get(structNumbers[i]).get("number");
            }
        }
        org.set("nckd_longname", String.join("_", longNames));
        org.set("nckd_longnumber", String.join("!", longNumbers));
    }


    static <T> Predicate<T> distinctByKey1(Function<? super T, ?> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap();
        return (t) -> {
            return seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
        };
    }

}
