package com.inspect.metadata.prodevmnt.util;

import com.inspect.metadata.prodevmnt.domain.vo.AreaDeviceTreeSelect;
import com.inspect.base.core.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

@Slf4j
public class AreaDeviceTreeSelectUtil {
    public static List<AreaDeviceTreeSelect> buildDeviceTree(List<AreaDeviceTreeSelect> areas) {
        List<AreaDeviceTreeSelect> returnList = new ArrayList<>();
        List<String> tempList = new ArrayList<>();
        Iterator<AreaDeviceTreeSelect> iterator = areas.iterator();
        AreaDeviceTreeSelect area;
        while (iterator.hasNext()) {
            area = iterator.next();
            tempList.add(area.getDataId());
        }

        iterator = areas.iterator();
        while (iterator.hasNext()) {
            area = iterator.next();
            if (!tempList.contains(area.getParentId())) {
                recursionFn(areas, area);
                returnList.add(area);
            }
        }

        if (returnList.isEmpty()) {
            returnList = areas;
        }

        return returnList;
    }

    public static List<AreaDeviceTreeSelect> buildDeviceTreeByAreaMeter(List<AreaDeviceTreeSelect> areaVOS) {
        List<AreaDeviceTreeSelect> returnList = new ArrayList<>();
        List<String> tempList = new ArrayList<>();
        Iterator<AreaDeviceTreeSelect> iterator = areaVOS.iterator();
        AreaDeviceTreeSelect area;
        while (iterator.hasNext()) {
            area = iterator.next();
            tempList.add(area.getDataId());
        }

        iterator = areaVOS.iterator();
        while (iterator.hasNext()) {
            area = iterator.next();
            if (!tempList.contains(area.getParentId())) {
                recursionFn(areaVOS, area);
                returnList.add(area);
            }
        }

        if (returnList.isEmpty()) {
            returnList = areaVOS;
        }

        return returnList;
    }

    public static List<AreaDeviceTreeSelect> buildDeviceTreeFilterByAreaName(List<AreaDeviceTreeSelect> areas, List<String> filterNameList) {
        List<AreaDeviceTreeSelect> returnList = new ArrayList<>();
        List<String> tempList = new ArrayList<>();
        Iterator<AreaDeviceTreeSelect> iterator = areas.iterator();
        AreaDeviceTreeSelect area;
        while (iterator.hasNext()) {
            area = iterator.next();
            tempList.add(area.getDataId());
        }

        iterator = areas.iterator();
        while (iterator.hasNext()) {
            area = iterator.next();
            if (!tempList.contains(area.getParentId()) && !shouldFilter(area, filterNameList)) {
                recursionFn(areas, area, filterNameList);
                returnList.add(area);
            }
        }

        if (returnList.isEmpty()) {
            returnList = areas;
        }

        return returnList;
    }

    // Helper method to determine if an area should be filtered out
    private static boolean shouldFilter(AreaDeviceTreeSelect area, List<String> filterNames) {
        return filterNames.stream().anyMatch(filterName -> StringUtils.isNotEmpty(area.getAreaName()) && area.getAreaName().equals(filterName));
    }

    private static void recursionFn(List<AreaDeviceTreeSelect> list, AreaDeviceTreeSelect t) {
        List<AreaDeviceTreeSelect> childList = getChildList(list, t);
        t.setChildren(childList);

        for (AreaDeviceTreeSelect tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }

    }

    private static void recursionFn(List<AreaDeviceTreeSelect> list, AreaDeviceTreeSelect t, List<String> filterNames) {
        List<AreaDeviceTreeSelect> childList = getChildList(list, t, filterNames);
        t.setChildren(childList);

        for (AreaDeviceTreeSelect tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild, filterNames);
            }
        }
    }

    private static List<AreaDeviceTreeSelect> getChildList(List<AreaDeviceTreeSelect> list, AreaDeviceTreeSelect t) {
        List<AreaDeviceTreeSelect> tlist = new ArrayList<>();

        for (AreaDeviceTreeSelect n : list) {
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().equals(t.getDataId())) {
                tlist.add(n);
            }
        }

        return tlist;
    }

    private static List<AreaDeviceTreeSelect> getChildList(List<AreaDeviceTreeSelect> list, AreaDeviceTreeSelect t, List<String> filterNames) {
        List<AreaDeviceTreeSelect> tlist = new ArrayList<>();

        for (AreaDeviceTreeSelect n : list) {
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().equals(t.getDataId()) && !shouldFilter(n, filterNames)) {
                tlist.add(n);
            }
        }

        return tlist;
    }

    private static boolean hasChild(List<AreaDeviceTreeSelect> list, AreaDeviceTreeSelect t) {
        return !getChildList(list, t).isEmpty();
    }
}
