package com.sonic.daosupport.wrapper;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sonic.common.exception.BizException;
import com.sonic.common.rpc.GlobalResultCode;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimaps;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.extern.slf4j.Slf4j;

/**
 * 将CriteriaWrapper转换为mysql的QueryWrapper
 * @author code
 */
@Slf4j
@Builder
@AllArgsConstructor
public class SimpleWrapperConverter {

    private final OperatorProcessor operatorProcessor;
    private final Map<String, String> fieldColumnMap;

    public QueryWrapper toWrapper(CriteriaWrapper criteriaWrapper) {
        ListMultimap<String, CriteriaWrapper.QueryField> multimap = criteriaWrapper.getQueryFieldMap()
                .asMap().entrySet().stream()
                .collect(Multimaps.flatteningToMultimap(
                        query -> getColumnNotNull(query.getKey()),
                        query -> convertValue(query.getValue()).stream(),
                        ArrayListMultimap::create));
        return operatorProcessor.assembleAllQueryWrapper(ImmutableListMultimap.copyOf(multimap), criteriaWrapper.getAndOperator());
    }

    /**
     * TODO: 暂时不支持返回 LambdaQueryWrapper
     * @param criteriaWrapper
     * @return
     */
    public LambdaQueryWrapper toLambdaWrapper(CriteriaWrapper criteriaWrapper) {
        ListMultimap<String, CriteriaWrapper.QueryField> multimap = criteriaWrapper.getQueryFieldMap()
                .asMap().entrySet().stream()
                .collect(Multimaps.flatteningToMultimap(
                        query -> getColumnNotNull(query.getKey()),
                        query -> convertValue(query.getValue()).stream(),
                        ArrayListMultimap::create));
        return operatorProcessor.assembleAllLambdaQueryWrapper(ImmutableListMultimap.copyOf(multimap), criteriaWrapper.getAndOperator());
    }

    public Optional<String> getColumn(String fieldName) {
        return Optional.ofNullable(fieldColumnMap.get(fieldName));
    }

    public String getColumnNotNull(String fieldName) {
        return getColumn(fieldName).orElseThrow(() -> new BizException(GlobalResultCode.INVALID_PARAMS));
    }

    /**
     * 转换QueryField的value
     *
     * @param queryFields
     * @return
     */
    private List<CriteriaWrapper.QueryField> convertValue(Collection<CriteriaWrapper.QueryField> queryFields) {
        return queryFields.stream()
                .map(queryField -> queryField.toBuilder().value(queryField.getValue()).build())
                .collect(Collectors.toList());
    }
}
