package com.fjhx.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import com.fjhx.base.BaseService;
import lombok.AllArgsConstructor;

import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 属性赋值构造器
 */
public class AttributeAssignBuilder<T, V> {

    /**
     * 服务
     */
    private final BaseService<T> service;

    /**
     * 原始数据
     */
    private final List<V> list;

    /**
     * 赋值方法集合
     */
    private final List<Fun> funList = new ArrayList<>();

    /**
     * 属性赋值构造器
     *
     * @param service 获取属性的表service
     * @param list    需要赋值的数组
     */
    private AttributeAssignBuilder(BaseService<T> service, List<V> list) {
        this.service = service;
        this.list = list;
    }

    /**
     * 初始化
     */
    public static <T, V> AttributeAssignBuilder<T, V> init(BaseService<T> service, List<V> list) {
        return new AttributeAssignBuilder<>(service, list);
    }

    /**
     * 添加赋值方法
     *
     * @param getIdFun        获取id方法
     * @param setAttributeFun 赋值属性方法
     * @return this
     */
    public AttributeAssignBuilder<T, V> assignFun(Function<V, Long> getIdFun, BiConsumer<V, T> setAttributeFun) {
        Fun fun = new Fun(getIdFun, setAttributeFun);
        funList.add(fun);
        return this;
    }

    /**
     * 执行赋值逻辑
     */
    public void build() {
        // 获取id集合
        Set<Long> idSet = getIdSet();
        if (idSet.size() == 0) {
            return;
        }

        // 查询Map<id,实体>
        Map<Long, T> entityMap = service.listByIds(idSet).stream().collect(Collectors.toMap(
                item -> Convert.toLong(BeanUtil.beanToMap(item).get("id")),
                item -> item
        ));
        if (entityMap.size() == 0) {
            return;
        }

        // 执行属性赋值方法
        attributeAssign(entityMap);
    }

    /**
     * 获取id集合
     *
     * @return id集合
     */
    private Set<Long> getIdSet() {
        Set<Long> idSet = new HashSet<>();
        for (V v : list) {
            for (Fun fun : funList) {
                Long userId = fun.getIdFun.apply(v);
                if (userId != null) {
                    idSet.add(userId);
                }
            }
        }
        return idSet;
    }

    /**
     * 属性赋值
     *
     * @param entityMap 实体map
     */
    private void attributeAssign(Map<Long, T> entityMap) {
        for (V v : list) {
            for (Fun fun : funList) {
                Long userId = fun.getIdFun.apply(v);
                if (userId == null) {
                    continue;
                }

                T t = entityMap.get(userId);
                if (t == null) {
                    continue;
                }

                fun.setAttributeFun.accept(v, t);
            }
        }
    }

    @AllArgsConstructor
    private class Fun {
        private Function<V, Long> getIdFun;
        private BiConsumer<V, T> setAttributeFun;
    }

}
