package com.boman.web.core.service.select;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.boman.common.core.utils.obj.ObjectUtils;
import com.boman.common.redis.RedisKey;
import com.boman.domain.GenTable;
import com.boman.domain.GenTableColumn;
import com.boman.domain.dto.FormDataDto;
import com.boman.web.core.mapper.StandardlyMapper;
import com.boman.web.core.service.TableServiceCmdService;
import com.boman.web.core.utils.ColumnUtils;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

import static com.boman.common.core.utils.obj.ObjectUtils.isEmpty;
import static com.boman.common.core.utils.obj.ObjectUtils.requireNonNull;

/**
 * @author shiqian
 * @date 2021年03月29日 10:22
 **/
@Service
public class BaseSelectServiceImpl implements IBaseSelectService {

    private static final Logger LOGGER = LoggerFactory.getLogger(BaseSelectServiceImpl.class);

    @Autowired
    private StandardlyMapper mapper;
    @Autowired
    private TableServiceCmdService cmdService;


    /**
     * 功能描述: 根据条件查询
     *
     * @param tableName     tableName
     * @param condition     原始查询条件
     * @param packCondition 封装的查询条件
     * @param showData      前台需要查询的列
     * @param dto           orderBy limit offset
     * @return java.util.List<com.alibaba.fastjson.JSONObject>
     */
    @Override
    public List<JSONObject> selectByCondition(String tableName, JSONObject condition, JSONObject packCondition, List<String> showData, FormDataDto dto) {
        requireNonNull(tableName, "表名为空");
        requireNonNull(showData, "表: [" + tableName + "] , 过滤了可展示字段，一个展示字段都没有，还查个鬼啊");
        String orderBy = requireNonNull(dto.getOrderBy(), "order by is empty");
        return mapper.selectByCondition(tableName, condition, packCondition, showData, orderBy, dto.getLimit(), dto.getOffset());
    }

    /**
     * 功能描述: 根据tableName和map(属性名和属性值)进行查查
     *
     * @param tableName tableName
     * @param param     属性名和属性值
     * @return java.util.List<com.alibaba.fastjson.JSONObject>
     */
    @Override
    public List<JSONObject> getByMap(String tableName, JSONObject param) {
        requireNonNull(tableName, "表名为空");

        // 判断condition中列是否都在此table中
        GenTable gent = cmdService.getTableFromRedisByTableName(RedisKey.TABLE_INFO, tableName);
        ColumnUtils.checkColumn(param, gent.getColumns());
        JSONObject packColCondition = ColumnUtils.packColCondition(gent.getColumns(), param);
        return mapper.getByMap(tableName, param, packColCondition, false);
    }


    /**
     * 功能描述: 根据tableName和map(属性名和属性值)进行查查
     *
     * @param tableName tableName
     * @param param     属性名和属性值
     * @return com.alibaba.fastjson.JSONObject
     */
    @Override
    public JSONObject getOneByMap(String tableName, JSONObject param) {
        requireNonNull(tableName, "表名为空");

        // 判断condition中列是否都在此table中
        GenTable gent = cmdService.getTableFromRedisByTableName(RedisKey.TABLE_INFO, tableName);
        ColumnUtils.checkColumn(param, gent.getColumns());
        JSONObject packColCondition = ColumnUtils.packColCondition(gent.getColumns(), param);
        List<JSONObject> result = mapper.getByMap(tableName, param, packColCondition, true);
        return isEmpty(result) ? null : result.get(0);
    }

    /**
     * 功能描述: 根据条件查询
     *
     * @param tableName     tableName
     * @param condition     原始查询条件
     * @param packCondition 封装的查询条件
     * @return int
     */
    @Override
    public int countByCondition(String tableName, JSONObject condition, JSONObject packCondition) {
        requireNonNull(tableName, "表名为空");

        return mapper.countByCondition(tableName, condition, packCondition);
    }

    /**
     * 功能描述: 根据id查所有，不支持自定义查询列
     *
     * @param tableName 表名
     * @param pkName    主键名称
     * @param id        主键值
     * @return com.alibaba.fastjson.JSONObject
     */
    @Override
    public JSONObject selectById(String tableName, String pkName, Long id, String other) {
        requireNonNull(tableName, "表名为空");
        requireNonNull(pkName, "主键名称为空");;
        requireNonNull(id, "selectById id is empty");
        return mapper.selectById(tableName, pkName, id, other);
    }

    /**
     * 功能描述: 根据id查所有，不支持自定义查询列
     *
     * @param tableName 表名
     * @param pkName    主键名称
     * @param ids        主键值
     * @return com.alibaba.fastjson.JSONObject
     */
    @Override
    public List<JSONObject> selectCandidatorsById(String tableName, String pkName, List<Long> ids, int type) {
        requireNonNull(tableName, "表名为空");
        requireNonNull(pkName, "主键名称为空");;
        requireNonNull(ids, "selectCandidatorsById id is empty");
        return mapper.selectCandidatorsById(tableName, pkName, ids, type);
    }

    /**
     * 功能描述: 根据id查所有，不支持自定义查询列
     *
     * @param tableName 表名
     * @param pkName    主键名称
     * @param idList    主键值
     * @param showData  需要展示的列
     * @return com.alibaba.fastjson.JSONObject
     */
    @Override
    public List<JSONObject> selectByIdList(String tableName, String pkName, List<Long> idList, List<String> showData) {
        requireNonNull(tableName, "表名为空");
        requireNonNull(pkName, "主键名称为空");;
        requireNonNull(idList, "selectByIdList idList is empty");

        return mapper.selectByIdList(tableName, pkName, idList, showData);
    }

    /**
     * 功能描述: 封装成查询条件 key: 列名，  value：查询条件_查询类别
     * eg: [{"config_name": ["系统配置", "EQ", "varchar(100)"]}]
     *
     * @param columns columns
     * @return com.alibaba.fastjson.JSONObject
     */
    @Override
    public JSONObject packColCondition(List<GenTableColumn> columns, JSONObject condition) {
        if (isEmpty(condition)) {
            return condition;
        }

        JSONObject result = new JSONObject(columns.size());
        for (Map.Entry<String, Object> entry : condition.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            for (GenTableColumn column : columns) {
                // long string collection 暂时只作此三种类型判断
                if (column.getColumnName().equalsIgnoreCase(key) && ObjectUtils.isNotEmpty(value)) {
                    // columnType 作为判断需不需要转义的一个标准，防止索引失效
                    result.put(key, Lists.newArrayList(value, column.getQueryType(), column.getColumnType()));
                    break;
                }
            }
        }

        return result;
    }

    /**
     * 功能描述: 获取最新的一条数据 create desc
     *
     * @param tableName tableName
     * @return jcom.alibaba.fastjson.JSONObject
     */
    @Override
    public JSONObject getNewest(String tableName) {
        requireNonNull(tableName, "tableName is empty");
        return mapper.getNewest(tableName);
    }
}
