package com.greenorange.promotion.service.common;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.service.IService;

import java.util.List;
import java.util.Map;
import java.util.function.Function;

public interface CommonService {


    /**
     * 从源集合中提取指定属性并作为查询条件查询目标集合
     *
     * @param sourceList      源集合（List<T>），包含需要提取属性的元素
     * @param service         执行查询的 MyBatis-Plus IService<R>
     * @param sourceField     提取源集合中每个元素的属性值的函数（如 T::getId）
     * @param targetField     目标集合中查询字段的函数引用（如 R::getForeignId）
     * @param <T>             源集合元素类型
     * @param <R>             目标集合中元素类型
     * @return 查询结果集合
     */
    <T, R> List<R> findByFieldInTargetField(
            List<T> sourceList,
            IService<R> service,
            Function<T, ?> sourceField,
            SFunction<R, ?> targetField
    );



    /**
     * 根据指定字段和值，使用给定的服务对象构建查询条件。
     *
     * @param <T>        实体类类型
     * @param field      目标查询字段的函数引用（如 User::getUsername）
     * @param fieldValue 查询字段的值
     * @param service    用于执行查询的服务层对象（可选，用于后续执行 list/query 等）
     * @return 返回构建的 LambdaQueryWrapper 对象，用于进一步查询或修改
     */
    <T> LambdaQueryWrapper<T> buildQueryWrapperByField(
            SFunction<T, ?> field,
            Object fieldValue,
            IService<T> service
    );


    /**
     * 根据指定字段和值，使用给定的服务对象查询对应的实体类列表。
     *
     * @param <T>         实体类类型
     * @param field       目标查询字段的函数引用（如 User::getUsername）
     * @param fieldValue  查询字段的值
     * @param service     用于执行查询的服务层对象
     * @return 返回符合条件的实体类列表（List<T>）。如果没有符合条件的记录，返回空列表。
     */
    <T> List<T> findByFieldEqTargetField(
            SFunction<T, ?> field,
            Object fieldValue,
            IService<T> service
    );


    /**
     * 根据多个字段和对应的值进行查询。
     * 该方法可以动态构建查询条件并执行查询。
     *
     * @param <T>              实体类类型
     * @param fieldConditions  查询条件的字段引用和值，使用 Map 存储
     *                         （key：R::getXxx，value：对应的查询值）
     * @param service          执行查询操作的服务对象（MyBatis-Plus 的 IService）
     * @return                 返回查询结果的列表
     */
    <T> List<T> findByFieldEqTargetFields(
            Map<SFunction<T, ?>, Object> fieldConditions,
            IService<T> service
    );




    /**
     * 将一个类型的 List 转换为另一个类型的 List。
     * @param sourceList 源列表，类型为 T
     * @param targetClass 目标类型的 Class 对象
     * @param <T> 源类型
     * @param <R> 目标类型
     * @return 转换后的目标类型列表
     */
    <T, R> List<R> convertList(List<T> sourceList, Class<R> targetClass);



    /**
     * 复制属性并返回新的目标对象
     *
     * @param source 源对象
     * @param targetClass 目标对象的类型
     * @param <S> 源对象类型
     * @param <T> 目标对象类型
     * @return 目标对象
     */
    <S, T> T copyProperties(S source, Class<T> targetClass);



    /**
     * 从源集合中提取指定属性并作为查询条件查询目标集合，同时只返回指定的属性。
     * 通过 MyBatis-Plus 的 `select` 方法，限制查询时返回的字段，避免查询不必要的字段，从而提高性能。
     *
     * @param sourceList      源集合（List<T>），包含需要提取属性的元素
     * @param service         执行查询的 MyBatis-Plus IService<R> 实例，用于调用数据库查询方法
     * @param sourceField     提取源集合中每个元素的属性值的函数（如 T::getId），用于获取源集合中元素的属性值
     * @param targetField     目标集合中查询字段的函数引用（如 R::getForeignId），用于指定查询条件
     * @param targetFields    需要返回的目标字段列表，包含希望从目标集合中查询的字段（如 R::getId, R::getName）
     * @param <T>             源集合元素类型
     * @param <R>             目标集合中元素类型
     * @return 查询结果集合，包含指定字段的数据，其他字段为 null
     */
    <T, R> List<R> findByFieldInTargetFieldWithSpecificFields(
            List<T> sourceList,
            IService<R> service,
            Function<T, ?> sourceField,
            SFunction<R, ?> targetField,
            List<SFunction<R, ?>> targetFields
    );


    /**
     * 根据指定字段和值，使用给定的服务对象查询对应的实体类列表，并且只返回指定的字段。
     *
     * @param <T>         实体类类型
     * @param field       目标查询字段的函数引用（如 User::getUsername）
     * @param fieldValue  查询字段的值
     * @param service     用于执行查询的服务层对象
     * @param targetFields 需要返回的目标字段列表
     * @return 返回符合条件的实体类列表（List<T>）。如果没有符合条件的记录，返回空列表。
     */
    <T> List<T> findByFieldEqTargetFieldWithSpecificFields(
            SFunction<T, ?> field,
            Object fieldValue,
            IService<T> service,
            List<SFunction<T, ?>> targetFields
    );


    /**
     * 根据多个字段和对应的值进行查询，同时只返回指定的字段。
     * 该方法可以动态构建查询条件并执行查询。
     *
     * @param <T>              实体类类型
     * @param fieldConditions  查询条件的字段引用和值，使用 Map 存储
     *                         （key：R::getXxx，value：对应的查询值）
     * @param service          执行查询操作的服务对象（MyBatis-Plus 的 IService）
     * @param targetFields     需要返回的目标字段列表
     * @return                 返回查询结果的列表，只包含指定的字段
     */
    <T> List<T> findByFieldEqTargetFieldsWithSpecificColumns(
            Map<SFunction<T, ?>, Object> fieldConditions,
            IService<T> service,
            List<SFunction<T, ?>> targetFields
    );


}
