package com.cool.store.vo;

import com.cool.store.entity.HyOpenAreaInfoDO;
import com.cool.store.enums.AreaStatusEnum;
import com.google.common.collect.Lists;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author suzhuhong
 * @Date 2023/6/2 10:55
 * @Version 1.0
 */
@Data
@ApiModel
@Slf4j
public class OpenAreaTreeVO {


    @ApiModelProperty("ID")
    private Long id;

    @ApiModelProperty("parent.id")
    private Long parentId;

    @ApiModelProperty("区域名称")
    private String areaName;

    @ApiModelProperty("区域路径")
    private String areaPath;

    @ApiModelProperty("状态 open-开放 keyOpen-重点开放 notOpen-未开放 saturated-已饱和")
    private String areaStatus;

    private String backgroundBanner;

    private String detailBanner;

    @ApiModelProperty("子区域")
    private List<OpenAreaTreeVO> childNode;


    public static List<OpenAreaTreeVO> convertTree(List<HyOpenAreaInfoDO> allOpenArea, String keyword, Boolean applyFlag){
        long startTime = System.currentTimeMillis();
        List<HyOpenAreaInfoDO> firstArea = allOpenArea.stream().filter(o -> Objects.isNull(o.getParentId())).collect(Collectors.toList());
        Map<Long, List<HyOpenAreaInfoDO>> openAreaParentMap = allOpenArea.stream().distinct().filter(o->Objects.nonNull(o.getParentId())).collect(Collectors.groupingBy(k -> k.getParentId()));
        List<OpenAreaTreeVO> allTree = new ArrayList<>();
        for (HyOpenAreaInfoDO openAreaInfo : firstArea) {
            OpenAreaTreeVO node = copyProperties(openAreaInfo);
            List<OpenAreaTreeVO> childList = dealChild(openAreaInfo, openAreaParentMap);
            node.setChildNode(childList);
            allTree.add(node);
        }
        //不需要过滤 直接返回
        if(StringUtils.isBlank(keyword) && (Objects.isNull(applyFlag) || !applyFlag)){
            return allTree;
        }
        log.info("1#耗时：{}", System.currentTimeMillis() - startTime);
        Map<Long, List<OpenAreaTreeVO>> childMap = allTree.stream().collect(Collectors.toMap(k -> k.getId(), v -> v.getChildNode()));
        List<HyOpenAreaInfoDO> filterList = allOpenArea.stream().filter(o -> (StringUtils.isBlank(keyword) || o.getAreaPath().contains(keyword))
                && (Objects.isNull(applyFlag) || AreaStatusEnum.OPEN.getCode().equals(o.getAreaStatus()) || AreaStatusEnum.OPEN.getCode().equals(o.getAreaStatus())))
                .collect(Collectors.toList());
        Map<Long, HyOpenAreaInfoDO> openAreaMap = allOpenArea.stream().collect(Collectors.toMap(k -> k.getId(), Function.identity()));
        List<HyOpenAreaInfoDO> filterAndParentList = new ArrayList<>();
        //向上处理节点
        for (HyOpenAreaInfoDO openAreaInfo : filterList) {
            filterAndParentList.add(openAreaInfo);
            while (Objects.nonNull(openAreaInfo) && Objects.nonNull(openAreaInfo.getParentId())){
                openAreaInfo = openAreaMap.get(openAreaInfo.getParentId());
                if(Objects.nonNull(openAreaInfo) && !filterAndParentList.contains(openAreaInfo)){
                    filterAndParentList.add(openAreaInfo);
                }
            }
        }
        log.info("2#耗时：{}", System.currentTimeMillis() - startTime);
        List<OpenAreaTreeVO> resultList = new ArrayList<>();
        List<HyOpenAreaInfoDO> filterFirstArea = filterAndParentList.stream().filter(o -> Objects.isNull(o.getParentId())).collect(Collectors.toList());
        Map<Long, List<HyOpenAreaInfoDO>> filterOpenAreaParentMap = filterAndParentList.stream().filter(Objects::nonNull).filter(o->Objects.nonNull(o.getParentId())).collect(Collectors.groupingBy(k -> k.getParentId()));
        for (HyOpenAreaInfoDO openAreaInfo : filterFirstArea) {
            Long id = openAreaInfo.getId();
            OpenAreaTreeVO node = copyProperties(openAreaInfo);
            List<OpenAreaTreeVO> childList = dealChild(openAreaInfo, filterOpenAreaParentMap);
            if(CollectionUtils.isEmpty(childList)){
                childList = childMap.get(node.getId());
            }
            node.setChildNode(childList);
            resultList.add(node);
        }
        log.info("2#耗时：{}", System.currentTimeMillis() - startTime);
        return resultList;
    }

    public static List<OpenAreaTreeVO> dealChild(HyOpenAreaInfoDO areaInfo, Map<Long, List<HyOpenAreaInfoDO>> openAreaParentMap){
        List<HyOpenAreaInfoDO> childList = openAreaParentMap.get(areaInfo.getId());
        if(CollectionUtils.isEmpty(childList)){
            return Lists.newArrayList();
        }
        List<OpenAreaTreeVO> resultList = new ArrayList<>();
        for (HyOpenAreaInfoDO hyOpenAreaInfo : childList) {
            OpenAreaTreeVO openAreaTree = copyProperties(hyOpenAreaInfo);
            openAreaTree.setChildNode(dealChild(hyOpenAreaInfo, openAreaParentMap));
            resultList.add(openAreaTree);
        }
        return resultList;
    }

    /**
     * 属性处理
     * @param area
     * @return
     */
    public static OpenAreaTreeVO copyProperties(HyOpenAreaInfoDO area){
        OpenAreaTreeVO result = new OpenAreaTreeVO();
        result.setId(area.getId());
        result.setParentId(area.getParentId());
        result.setAreaName(area.getAreaName());
        result.setAreaPath(area.getAreaPath());
        result.setAreaStatus(area.getAreaStatus());
        result.setBackgroundBanner(area.getBackgroundBanner());
        result.setDetailBanner(area.getDetailBanner());
        return result;
    }
}
