package com.fjhx.util;

import cn.hutool.extra.spring.SpringUtil;
import com.fjhx.entity.Material;
import com.fjhx.service.MaterialService;
import lombok.AllArgsConstructor;
import lombok.Getter;

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

/**
 * 用户属性赋值工具类
 */
@AllArgsConstructor
public class MaterialAttributeAssignUtil<T> {

    /**
     * 物料service
     */
    private static final MaterialService materialService = SpringUtil.getBean(MaterialService.class);

    /**
     * 初始化
     */
    public static <T> MaterialAttributeAssignUtil<T> init(List<T> list) {
        return new MaterialAttributeAssignUtil<>(list);
    }

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

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

    /**
     * 添加物料信息方法
     *
     * @param getMaterialIdFun 获取物料id方法
     * @param setAttributeFun  赋值物料属性方法
     * @return this
     */
    public MaterialAttributeAssignUtil<T> assignFun(Function<T, Long> getMaterialIdFun, BiConsumer<T, Material> setAttributeFun) {
        Fun fun = new Fun(getMaterialIdFun, setAttributeFun);
        funList.add(fun);
        return this;
    }

    /**
     * 执行赋值逻辑
     */
    public void execute() {
        // 获取物料id集合
        Set<Long> materialIdList = new HashSet<>();
        for (T t : list) {
            for (Fun fun : funList) {
                Long userId = fun.getAssignMaterialIdFun().apply(t);
                if (userId != null) {
                    materialIdList.add(userId);
                }
            }
        }
        if (materialIdList.size() == 0) {
            return;
        }

        // 查询物料id实体Map
        Map<Long, Material> materialByIdMap = materialService.getKEntity(Material::getId, q -> q.in(Material::getId, materialIdList));
        if (materialByIdMap.size() == 0) {
            return;
        }

        // 赋值用户昵称
        for (T t : list) {
            for (Fun fun : funList) {
                Long userId = fun.getAssignMaterialIdFun().apply(t);
                if (userId == null) {
                    continue;
                }

                Material material = materialByIdMap.get(userId);
                if (material == null) {
                    continue;
                }

                fun.getAssignUserStrFun().accept(t, material);
            }
        }

    }

    @Getter
    @AllArgsConstructor
    private class Fun {
        private Function<T, Long> assignMaterialIdFun;
        private BiConsumer<T, Material> assignUserStrFun;
    }

}
