package jnpf.util.permssion;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import jnpf.model.common.CheckVo;
import jnpf.permission.model.util.IdDiffResult;
import jnpf.permission.model.util.IdPair;
import jnpf.permission.model.util.IdPairDiffResult;
import jnpf.permission.vo.TreeNodeVo;
import jnpf.util.JsonUtil;

import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * todo
 *
 * @author Flynn Chan
 * @create 2025-10-02
 */
public class V2Utils {


    public static <T extends TreeNodeVo<T>> List<T> changeToTreeNoParent(List<T> list, Class<T> c) {

        CheckVo checkVo = new CheckVo(false);
        List<T> listCopy = JsonUtil.getJsonToList(list, c);
        for (T t : list) {
            T tt = listCopy.stream().filter(v -> v.getId().equals(t.getId())).findFirst().orElse(null);
            if (tt == null) {
                continue;
            }
            findParent(checkVo, listCopy, tt);
            if (checkVo.getFlag()) {
                listCopy.removeIf(v -> v.getId().equals(t.getId()));
                checkVo.setFlag(false);
            }
        }
        return listCopy;
    }

    public static <T extends TreeNodeVo<T>> List<T> changeToTreeNoParentFast(List<T> list, Class<T> c) {
        // 拷贝副本
        List<T> listCopy = BeanUtil.copyToList(list, c);

        // 构建 Map 方便快速访问
        Map<String, T> nodeMap = listCopy.stream().collect(Collectors.toMap(T::getId, Function.identity()));

        // 存放根节点
        List<T> rootList = new ArrayList<>();

        for (T node : listCopy) {
            String pid = node.getPid();
            if (StrUtil.isNotBlank(pid) && nodeMap.containsKey(pid)) {
                T parent = nodeMap.get(pid);
                parent.getChildren().add(node);
            } else {
                rootList.add(node);
            }
        }

        return rootList;
    }


    private static <T extends TreeNodeVo<T>> void findParent(CheckVo checkVo, List<T> list, T t) {

        if (!list.isEmpty()) {
            for (T value : list) {
                if (value.getId().equals(t.getPid())) {
                    value.getChildren().add(t);
                    checkVo.setFlag(true);
                    return;
                }
                findParent(checkVo, value.getChildren(), t);
            }
        }
    }

    public static <T extends TreeNodeVo<T>> void nodeAddChildren(List<T> list, ConcurrentMap<String, List<T>> map) {

        if (!list.isEmpty()) {
            for (T value : list) {
                List<T> children = map.get(value.getId());
                if (null != children && !children.isEmpty()) {
                    value.getChildren().addAll(children);
                }
                nodeAddChildren(value.getChildren(), map);
            }
        }
    }

    /**
     * 树递归排序
     *
     * @param list 数据源
     */
    public static <T extends TreeNodeVo<T>> void treeSort(List<T> list) {

        if (!list.isEmpty()) {
            list.sort(Comparator.nullsLast(Comparator.comparing(t -> t.getChildren().size(), Comparator.nullsLast(Comparable::compareTo))));
            for (T value : list) {
                treeSort(value.getChildren());
            }
        }
    }

    /**
     * 将对象base64编码
     *
     * @param jsonToBean 对象
     * @return base64编码字符串
     */
    public static String encodeJson(Object jsonToBean) {
        return new JSONObject(jsonToBean).toString();
    }

    /**
     * 把逗号分隔的字符串转换为数组
     *
     * @param input
     * @return
     */
    public static List<String> convertToList(String input) {
        if (input == null || input.trim().isEmpty()) {
            return Collections.emptyList();
        }

        // 判断格式是否符合：多个用逗号隔开的非空串
        if (!input.matches("^(\\S+)(,\\S+)*$")) {
            return Collections.emptyList();
        }

        // 拆分并转为 List
        return new ArrayList<>(Arrays.asList(input.split(",")));
    }

    /**
     * 始终取list最后一条数据并且剔除,没有则空
     */
    public static String pollLast(List<String> list) {
        if (list == null || list.isEmpty()) {
            return null;
        }
        // 移除并返回最后一条
        return list.remove(list.size() - 1);
    }

    /**
     * 使用 Set 比较两个 ID 列表，适用于大数据量。
     *
     * @param oldIds    原始 ID 列表
     * @param targetIds 目标 ID 列表
     * @return 包含 removedIds 和 addedIds 的结果对象
     */
    public static IdDiffResult compareIdLists(List<String> oldIds, List<String> targetIds) {
        oldIds = oldIds == null ? new ArrayList<>() : oldIds;
        targetIds = targetIds == null ? new ArrayList<>() : targetIds;
        Set<String> oldSet = new HashSet<>(oldIds);
        Set<String> targetSet = new HashSet<>(targetIds);

        Set<String> removedSet = new HashSet<>(oldSet);
        removedSet.removeAll(targetSet);

        Set<String> addedSet = new HashSet<>(targetSet);
        addedSet.removeAll(oldSet);

        return new IdDiffResult(new ArrayList<>(removedSet), new ArrayList<>(addedSet));
    }


    /**
     * 获取两个列表对象(两个String属性)的差异
     *
     * @param oldList    旧列表
     * @param targetList 新列表
     */
    public static IdPairDiffResult compareIdPairs(List<IdPair> oldList, List<IdPair> targetList) {
        oldList = oldList == null ? new ArrayList<>() : oldList;
        targetList = targetList == null ? new ArrayList<>() : targetList;

        // 用 id1-id2 作为唯一 key 做对比
        Map<String, IdPair> oldMap = oldList.stream()
                .collect(Collectors.toMap(V2Utils::buildKey, p -> p));

        Map<String, IdPair> targetMap = targetList.stream()
                .collect(Collectors.toMap(V2Utils::buildKey, p -> p));

        Set<String> oldKeys = oldMap.keySet();
        Set<String> targetKeys = targetMap.keySet();

        // removed: old 有而 target 没有的 key
        List<IdPair> removed = oldKeys.stream()
                .filter(k -> !targetKeys.contains(k))
                .map(oldMap::get)
                .collect(Collectors.toList());

        // added: target 有而 old 没有的 key
        List<IdPair> added = targetKeys.stream()
                .filter(k -> !oldKeys.contains(k))
                .map(targetMap::get)
                .collect(Collectors.toList());

        return new IdPairDiffResult(removed, added);
    }

    private static String buildKey(IdPair pair) {
        return (pair.getId1() == null ? "" : pair.getId1()) + "-" + (pair.getId2() == null ? "" : pair.getId2());
    }


    // 提取字符串中的第一个连续数字
    public static Integer extractNumber(String str) {
        if (str == null) return null;
        java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("\\d+");
        java.util.regex.Matcher matcher = pattern.matcher(str);
        if (matcher.find()) {
            return Integer.parseInt(matcher.group());
        }
        return null;
    }

    /**
     * 根据倒序索引获取单个组织ID
     *
     * @param organizeIdTree 逗号分隔的组织ID树
     * @param count          倒序第几个，1表示最后一个，2表示倒数第二个
     * @return 对应的ID，如果越界返回 null
     */
    public static String getIdByReverseOrder(String organizeIdTree, int count) {
        if (organizeIdTree == null || organizeIdTree.isEmpty() || count <= 0) {
            return null;
        }
        String[] ids = organizeIdTree.split(",");
        int index = ids.length - count;
        if (index < 0) {
            return null; // 越界时返回 null
        }
        return ids[index];
    }

    /**
     * 获取最后 count 个组织ID
     *
     * @param organizeIdTree 逗号分隔的组织ID树
     * @param count          要返回的个数（从最后往前数）
     * @return List<String>，如果 count 超过长度则返回全部
     */
    public static List<String> getLastIds(String organizeIdTree, int count) {
        if (organizeIdTree == null || organizeIdTree.isEmpty() || count <= 0) {
            return Collections.emptyList();
        }
        String[] ids = organizeIdTree.split(",");
        int length = ids.length;

        int start = Math.max(length - count, 0);

        return new ArrayList<>(Arrays.asList(ids).subList(start, length));
    }
}
