package com.ruoyi.common.core.service;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.common.utils.wrapper.IWrapper;

import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;

@SuppressWarnings({"unused", "unchecked"})
public interface BaseService<T> extends IService<T> {


    default IWrapper<T> getWrapper() {
        return IWrapper.getWrapper();
    }

    // =========================================================
    // mp方法扩展
    // =========================================================

    default void assertExecutable(Consumer<LambdaQueryWrapper<T>> consumer, String errorMsgTemplate, Object... params) {
        long count = count(consumer);
        Assert.equals(count, 0L, errorMsgTemplate, params);
    }

    default long count(Consumer<LambdaQueryWrapper<T>> consumer) {
        return count(Wrappers.<T>lambdaQuery().func(ObjectUtil.isNotEmpty(consumer), consumer));
    }

    default T getOne(Consumer<LambdaQueryWrapper<T>> consumer) {
        return getOne(Wrappers.<T>lambdaQuery().func(ObjectUtil.isNotEmpty(consumer), consumer).last("limit 1"));
    }

    default List<T> list(Consumer<LambdaQueryWrapper<T>> consumer) {
        return list(Wrappers.<T>lambdaQuery().func(ObjectUtil.isNotEmpty(consumer), consumer));
    }

    default List<Map<String, Object>> listMaps(Consumer<LambdaQueryWrapper<T>> consumer) {
        return listMaps(Wrappers.<T>lambdaQuery().func(ObjectUtil.isNotEmpty(consumer), consumer));
    }

    default <K> List<K> listObject(SFunction<T, K> mapper, Consumer<LambdaQueryWrapper<T>> consumer) {
        return listObjs(Wrappers.<T>lambdaQuery().select(mapper).func(ObjectUtil.isNotEmpty(consumer), consumer), t -> (K) t);
    }

    default <K, V> Map<K, V> mapKV(SFunction<T, K> kFun, SFunction<T, V> vFun, Consumer<LambdaQueryWrapper<T>> consumer) {
        List<T> list = list(Wrappers.<T>lambdaQuery().select(kFun, vFun).func(ObjectUtil.isNotEmpty(consumer), consumer));
        return list.stream().collect(Collectors.toMap(kFun, vFun, (v1, v2) -> v2));
    }

    default <K> Map<K, T> mapKEntity(SFunction<T, K> kFun, Consumer<LambdaQueryWrapper<T>> consumer) {
        List<T> list = list(Wrappers.<T>lambdaQuery().func(ObjectUtil.isNotEmpty(consumer), consumer));
        return list.stream().collect(Collectors.toMap(kFun, item -> item, (v1, v2) -> v2));
    }

    default <K> Map<K, List<T>> mapKGroup(SFunction<T, K> kFun, Consumer<LambdaQueryWrapper<T>> consumer) {
        List<T> list = list(Wrappers.<T>lambdaQuery().func(ObjectUtil.isNotEmpty(consumer), consumer));
        return list.stream().collect(Collectors.groupingBy(kFun));
    }

    default boolean update(Consumer<LambdaUpdateWrapper<T>> consumer) {
        return update(Wrappers.<T>lambdaUpdate().func(ObjectUtil.isNotEmpty(consumer), consumer));
    }

    default boolean remove(Consumer<LambdaQueryWrapper<T>> consumer) {
        return remove(Wrappers.<T>lambdaQuery().func(ObjectUtil.isNotEmpty(consumer), consumer));
    }

}
