package com.orion.visor.framework.mybatis.core.query;

import com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper;
import com.baomidou.mybatisplus.core.conditions.SharedString;
import com.baomidou.mybatisplus.core.conditions.query.Query;
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;

/**
 * 复制 LambdaQueryWrapper
 * 实现 Then
 *
 * @author Jiahang Li
 * @version 1.0.0
 * @since 2023/10/8 15:13
 */
public class ThenLambdaWrapper<T> extends AbstractLambdaWrapper<T, ThenLambdaWrapper<T>>
        implements Query<ThenLambdaWrapper<T>, T, SFunction<T, ?>>, Then<DataQuery<T>> {

    private final DataQuery<T> dataQuery;

    /**
     * 查询字段
     */
    private SharedString sqlSelect = new SharedString();

    public ThenLambdaWrapper(DataQuery<T> dataQuery) {
        this((T) null, dataQuery);
    }

    public ThenLambdaWrapper(T entity, DataQuery<T> dataQuery) {
        super.setEntity(entity);
        super.initNeed();
        this.dataQuery = dataQuery;
    }

    ThenLambdaWrapper(T entity, Class<T> entityClass, SharedString sqlSelect, AtomicInteger paramNameSeq,
                      Map<String, Object> paramNameValuePairs, MergeSegments mergeSegments, SharedString paramAlias,
                      SharedString lastSql, SharedString sqlComment, SharedString sqlFirst, DataQuery<T> dataQuery) {
        super.setEntity(entity);
        super.setEntityClass(entityClass);
        this.paramNameSeq = paramNameSeq;
        this.paramNameValuePairs = paramNameValuePairs;
        this.expression = mergeSegments;
        this.sqlSelect = sqlSelect;
        this.paramAlias = paramAlias;
        this.lastSql = lastSql;
        this.sqlComment = sqlComment;
        this.sqlFirst = sqlFirst;
        this.dataQuery = dataQuery;
    }

    @SafeVarargs
    @Override
    public final ThenLambdaWrapper<T> select(SFunction<T, ?>... columns) {
        return select(Arrays.asList(columns));
    }

    public ThenLambdaWrapper<T> select(List<SFunction<T, ?>> columns) {
        if (CollectionUtils.isNotEmpty(columns)) {
            this.sqlSelect.setStringValue(columnsToString(false, columns));
        }
        return typedThis;
    }

    @Override
    public ThenLambdaWrapper<T> select(Class<T> entityClass, Predicate<TableFieldInfo> predicate) {
        if (entityClass == null) {
            entityClass = getEntityClass();
        } else {
            setEntityClass(entityClass);
        }
        Assert.notNull(entityClass, "entityClass can not be null");
        this.sqlSelect.setStringValue(TableInfoHelper.getTableInfo(entityClass).chooseSelect(predicate));
        return typedThis;
    }

    @Override
    public String getSqlSelect() {
        return sqlSelect.getStringValue();
    }

    @Override
    protected ThenLambdaWrapper<T> instance() {
        return new ThenLambdaWrapper<>(getEntity(), getEntityClass(), null, paramNameSeq, paramNameValuePairs,
                new MergeSegments(), paramAlias, SharedString.emptyString(), SharedString.emptyString(), SharedString.emptyString(),
                dataQuery);
    }

    @Override
    public void clear() {
        super.clear();
        sqlSelect.toNull();
    }

    @Override
    public DataQuery<T> then() {
        return dataQuery;
    }

}
