package com.kym.service.mybatisplus;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.github.yulichang.base.MPJBaseService;
import com.kym.mapper.mybatisplus.MyBaseMapper;
import org.apache.ibatis.binding.MapperMethod;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.function.Function;

/**
 * 扩展mybatis-plus，支持按照指定字段更新单挑或批量数据
 *
 * @author skyline
 */
public class MyBaseServiceImpl<M extends MyBaseMapper<T>, T> extends ServiceImpl<M, T> implements MPJBaseService<T>, MyBaseService<T> {



    /**
     * 根据指定字段批量更新
     *
     * @param entityList
     * @param queryWrapperFunction
     * @return
     */
    @Override
    public boolean updateBatchByQueryWrapper(Collection<T> entityList, Function<T, QueryWrapper<T>> queryWrapperFunction) {
        String sqlStatement = this.getSqlStatement(SqlMethod.UPDATE);
        return this.executeBatch(entityList, DEFAULT_BATCH_SIZE, (sqlSession, entity) -> {
            MapperMethod.ParamMap param = new MapperMethod.ParamMap<>();
            param.put(Constants.ENTITY, entity);
            param.put(Constants.WRAPPER, queryWrapperFunction.apply(entity));
            sqlSession.update(sqlStatement, param);
        });
    }

    /**
     * 根据指定字段更新单条数据
     *
     * @param entity
     * @param queryWrapperFunction
     * @return
     */
    @Override
    public boolean updateByQueryWrapper(T entity, Function<T, QueryWrapper<T>> queryWrapperFunction) {
        return SqlHelper.retBool(getBaseMapper().update(entity, queryWrapperFunction.apply(entity)));
    }

    @Override
    public int insertIgnore(T entity) {
        return baseMapper.insertIgnore(entity);
    }

    @Override
    public int replace(T entity) {
        return baseMapper.replace(entity);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean replaceBatch(Collection<T> entityList) {
        String sqlStatement = getSqlStatement(MySqlMethod.REPLACE_ONE);
        return executeBatch(entityList, DEFAULT_BATCH_SIZE, (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity));
    }

    protected String getSqlStatement(MySqlMethod sqlMethod) {
        return getSqlStatement(getMapperClass(), sqlMethod);
    }

    public static String getSqlStatement(Class<?> mapper, MySqlMethod sqlMethod) {
        return mapper.getName() + StringPool.DOT + sqlMethod.getMethod();
    }


}
