package com.common.base.module.data.module;

import com.common.base.common.WebPageInfo;
import com.common.base.common.utils.MyPageHelper;
import com.common.base.common.utils.StringUtils;
import com.common.base.module.data.dao.TableMapper;
import com.common.base.module.data.exception.BaseMapperException;
import com.common.base.module.data.exception.SqlException;
import com.common.base.module.datasource.dynamic.DBContextHolder;
import com.common.base.module.datasource.entity.DatasourceConfig;
import com.common.base.module.datasource.utils.DataSourceUtil;
import com.common.base.module.datasource.utils.DataUnit;
import com.common.base.module.tableconfig.entity.OsSysTable;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Service
@Qualifier("base")
public class BaseMapperImpl implements BaseMapper {

    public static final String BASE = "base";

    final TableMapper tableMapper;

    public BaseMapperImpl(TableMapper tableMapper) {
        this.tableMapper = tableMapper;
    }

    @Override
    @Transactional
    public int save(DataMap dataMap) {
        String key;
        key = DBContextHolder.getDataSource();
        DatasourceConfig datasourceConfig = DataSourceUtil.get(key);
        JudgesNull(dataMap.getData(), "data can not be null!");
        JudgesNull(dataMap.getTableName(), "tableName can not be null!");
        if (StringUtils.isEmpty(dataMap.getPkName())) {
            dataMap.setPkName("ID");
        }
        int i;
        if (datasourceConfig.getCommonType().equals(DataUnit.ORACLE)||datasourceConfig.getCommonType().equals(DataUnit.DAMENG)) {
            if (org.springframework.util.StringUtils.isEmpty(dataMap.get(dataMap.getPkName()))) {
                dataMap.toBuilder().add(dataMap.getPkName(), getSequence(dataMap.getTableName(), dataMap.getPkName()));
            }
            i = tableMapper.saveInfoWithOracle(dataMap.getData(), dataMap.getTableName());
        } else {
            i = tableMapper.saveInfoWithNull(dataMap.getData(), dataMap.getTableName());
            dataMap.toBuilder().add(dataMap.getPkName(), dataMap.getData().get("id")).build();
        }
        SqlException.base(i, "保存失败");
        dataMap.toBuilder().remove("id");
        return i;
    }

    @Override
    @Transactional
    public int save(String tableName, String pkName, Map<String, Object> data) {
        JudgesNull(tableName, "data can not be null!");
        JudgesNull(data, "tableName can not be null!");
        String key = DBContextHolder.getDataSource();
        DatasourceConfig datasourceConfig = DataSourceUtil.get(key);
        if (StringUtils.isEmpty(pkName)) {
            pkName = "ID";
        }
        int i;
        if (datasourceConfig.getCommonType().equals(DataUnit.ORACLE)||datasourceConfig.getCommonType().equals(DataUnit.DAMENG)) {
            if (org.springframework.util.StringUtils.isEmpty(data.get(pkName))) {
                data.put(pkName, getSequence(tableName, pkName));
            }
            i = tableMapper.saveInfoWithOracle(data, tableName);
        } else {
            i = tableMapper.saveInfoWithNull(data, tableName);
            data.put(pkName, data.get("id"));
        }
        SqlException.base(i, "保存失败");
        data.remove("id");
        return i;
    }


    @Override
    public int updateByPk(DataMap dataMap) {
        JudgesNull(dataMap.getData(), "data can not be null!");
        JudgesNull(dataMap.getTableName(), "tableName can not be null!");
        JudgesNull(dataMap.getPkName(), "pkName can not be null!");
        JudgesNull(dataMap.getPkValue(), "pkValue can not be null!");
        Condition condition = Condition.creatCriteria()
                .andEqual(dataMap.getPkName(), dataMap.getPkValue())
                .build();
        int i = tableMapper.updateByWhere(dataMap.getData(), dataMap.getTableName(), condition.getSql());
        SqlException.base(i, "更新失败");
        return i;
    }

    @Override
    public int updateByPk(String tableName, String pkName, Object pkValue, Map<String, Object> data) {
        JudgesNull(data, "data can not be null!");
        JudgesNull(tableName, "tableName can not be null!");
        JudgesNull(pkName, "pkName can not be null!");
        JudgesNull(pkValue, "pkValue can not be null!");
        Condition condition = Condition.creatCriteria()
                .andEqual(pkName, pkValue)
                .build();
        int i = tableMapper.updateByWhere(data, tableName, condition.getSql());
        SqlException.base(i, "更新失败");
        return i;
    }

    @Override
    public int updateByPk(OsSysTable osSysTable, Object pkValue, Map<String, Object> data) {
        JudgesNull(data, "data can not be null!");
        JudgesNull(osSysTable.getTableName(), "tableName can not be null!");
        JudgesNull(osSysTable.getTablePk(), "pkName can not be null!");
        JudgesNull(pkValue, "pkValue can not be null!");
        Condition condition = Condition.creatCriteria()
                .andEqual(osSysTable.getTablePk(), pkValue)
                .build();
        int i = tableMapper.updateByWhere(data, osSysTable.getTableName(), condition.getSql());
        SqlException.base(i, "更新失败");
        return i;
    }


    @Override
    public int updateInPk(DataMap dataMap) {
        JudgesNull(dataMap.getData(), "data can not be null!");
        JudgesNull(dataMap.getTableName(), "tableName can not be null!");
        JudgesNull(dataMap.getPkName(), "pkName can not be null!");
        JudgesNull(dataMap.getIds(), "ids can not be null!");
        Condition condition = Condition.creatCriteria()
                .andIn(dataMap.getPkName(), dataMap.getIdList())
                .build();
        int i = tableMapper.updateByWhere(dataMap.getData(), dataMap.getTableName(), condition.getSql());
        SqlException.base(i, "更新失败");
        return i;
    }

    @Override
    public <E> int updateInPk(String tableName, String pkName, List<E> ids, Map<String, Object> data) {
        JudgesNull(data, "data can not be null!");
        JudgesNull(tableName, "tableName can not be null!");
        JudgesNull(pkName, "pkName can not be null!");
        JudgesNull(ids, "ids can not be null!");
        Condition condition = Condition.creatCriteria()
                .andIn(pkName, ids)
                .build();
        int i = tableMapper.updateByWhere(data, tableName, condition.getSql());
        SqlException.base(i, "更新失败");
        return i;
    }

    @Override
    public <E> int updateInPk(OsSysTable osSysTable, List<E> ids, Map<String, Object> data) {
        JudgesNull(data, "data can not be null!");
        JudgesNull(osSysTable.getTableName(), "tableName can not be null!");
        JudgesNull(osSysTable.getTablePk(), "pkName can not be null!");
        JudgesNull(ids, "ids can not be null!");
        Condition condition = Condition.creatCriteria()
                .andIn(osSysTable.getTablePk(), ids)
                .build();
        int i = tableMapper.updateByWhere(data, osSysTable.getTableName(), condition.getSql());
        SqlException.base(i, "更新失败");
        return i;
    }


    @Override
    public int updateByCondition(DataMap dataMap, Condition condition) {
        JudgesNull(dataMap.getData(), "data can not be null!");
        JudgesNull(dataMap.getTableName(), "tableName can not be null!");
        int i = tableMapper.updateByWhere(dataMap.getData(), dataMap.getTableName(), condition.getSql());
        SqlException.base(i, "更新失败");
        return i;
    }

    @Override
    public int updateByCondition(String tableName, Map<String, Object> data, Condition condition) {
        JudgesNull(data, "data can not be null!");
        JudgesNull(tableName, "tableName can not be null!");
        int i = tableMapper.updateByWhere(data, tableName, condition.getSql());
        SqlException.base(i, "更新失败");
        return i;
    }

    @Override
    public int deleteByPk(DataMap dataMap) {
        JudgesNull(dataMap.getPkValue(), "pkValue can not be null!");
        JudgesNull(dataMap.getPkName(), "pkName can not be null!");
        JudgesNull(dataMap.getTableName(), "tableName can not be null!");
        Condition condition = Condition.creatCriteria()
                .andEqual(dataMap.getPkName(), dataMap.getPkValue())
                .build();
        int i = tableMapper.deleteByWhere(dataMap.getTableName(), condition.getSql());
        SqlException.base(i, "删除失败");
        return i;
    }

    @Override
    public int deleteByPk(String tableName, String pkName, Object pkValue) {
        JudgesNull(pkValue, "pkValue can not be null!");
        JudgesNull(pkName, "pkName can not be null!");
        JudgesNull(tableName, "tableName can not be null!");
        Condition condition = Condition.creatCriteria()
                .andEqual(pkName, pkValue)
                .build();
        int i = tableMapper.deleteByWhere(tableName, condition.getSql());
        SqlException.base(i, "删除失败");
        return i;
    }

    @Override
    public int deleteByPk(OsSysTable osSysTable, Object pkValue) {
        JudgesNull(pkValue, "pkValue can not be null!");
        JudgesNull(osSysTable.getTablePk(), "pkName can not be null!");
        JudgesNull(osSysTable.getTableName(), "tableName can not be null!");
        Condition condition = Condition.creatCriteria()
                .andEqual(osSysTable.getTablePk(), pkValue)
                .build();
        int i = tableMapper.deleteByWhere(osSysTable.getTableName(), condition.getSql());
        SqlException.base(i, "删除失败");
        return i;
    }

    @Override
    public <E> int deleteInPk(String tableName, String pkName, List<E> ids) {
        JudgesNull(tableName, "tableName can not be null!");
        JudgesNull(pkName, "pkName can not be null!");
        JudgesNull(ids, "ids can not be null!");
        Condition condition = Condition.creatCriteria()
                .andIn(pkName, ids)
                .build();
        int i = tableMapper.deleteByWhere(tableName, condition.getSql());
        SqlException.base(i, "删除失败");
        return i;
    }

    @Override
    public int deleteInPk(DataMap dataMap) {
        JudgesNull(dataMap.getTableName(), "tableName can not be null!");
        JudgesNull(dataMap.getPkName(), "pkName can not be null!");
        JudgesNull(dataMap.getIds(), "ids can not be null!");
        Condition condition = Condition.creatCriteria()
                .andIn(dataMap.getPkName(), dataMap.getIdList())
                .build();
        int i = tableMapper.deleteByWhere(dataMap.getTableName(), condition.getSql());
        SqlException.base(i, "删除失败");
        return i;
    }

    @Override
    public <E> int deleteInPk(OsSysTable osSysTable, List<E> ids) {
        JudgesNull(osSysTable.getTableName(), "tableName can not be null!");
        JudgesNull(osSysTable.getTablePk(), "pkName can not be null!");
        JudgesNull(ids, "ids can not be null!");
        Condition condition = Condition.creatCriteria()
                .andIn(osSysTable.getTablePk(), ids)
                .build();
        int i = tableMapper.deleteByWhere(osSysTable.getTableName(), condition.getSql());
        SqlException.base(i, "删除失败");
        return i;
    }

    @Override
    public int deleteByCondition(DataMap dataMap, Condition condition) {
        JudgesNull(dataMap.getTableName(), "tableName can not be null!");
        int i = tableMapper.deleteByWhere(dataMap.getTableName(), condition.getSql());
        SqlException.base(i, "删除失败");
        return i;
    }

    @Override
    public int deleteByCondition(String tableName, Condition condition) {
        JudgesNull(tableName, "tableName can not be null!");
        int i = tableMapper.deleteByWhere(tableName, condition.getSql());
        SqlException.base(i, "删除失败");
        return i;
    }

    @Override
    public List<Map<String, Object>> selectAll(String tableName) {
        JudgesNull(tableName, "tableName can not be null!");
        return tableMapper.useSql(SelectCondition.builder().tableName(tableName).build().getSql());
    }

    @Override
    public List<Map<String, Object>> selectByEqual(DataMap dataMap, Map<String, Object> map) {
        JudgesNull(dataMap.getTableName(), "tableName can not be null!");
        Condition condition = equal(dataMap, map);
        return tableMapper.useSql(condition.getSql());
    }

    @Override
    public List<Map<String, Object>> selectByEqual(String tableName, Map<String, Object> map) {
        JudgesNull(tableName, "tableName can not be null!");
        Condition condition = equal(DataMap.builder().tableName(tableName).build(), map);
        return tableMapper.useSql(condition.getSql());
    }

    private Condition equal(DataMap dataMap, Map<String, Object> map) {
        Condition condition = Condition.creatCriteria(dataMap).build();
        if (map != null && !map.isEmpty()) {
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                condition = condition
                        .toCreatCriteria()
                        .andEqual(entry.getKey(), entry.getValue())
                        .build();
            }
        }
        return condition;
    }

    @Override
    public PageInfo<Map<String, Object>> selectByEqual(DataMap dataMap, Map<String, Object> map, WebPageInfo webPageInfo) {
        JudgesNull(dataMap.getTableName(), "tableName can not be null!");
        MyPageHelper.start(webPageInfo);
        Condition condition = equal(dataMap, map);
        return new PageInfo<>(tableMapper.useSql(condition.getSql()));
    }

    @Override
    public PageInfo<Map<String, Object>> selectByEqual(String tableName, Map<String, Object> map, WebPageInfo webPageInfo) {
        JudgesNull(tableName, "tableName can not be null!");
        MyPageHelper.start(webPageInfo);
        Condition condition = equal(DataMap.builder().tableName(tableName).build(), map);
        return new PageInfo<>(tableMapper.useSql(condition.getSql()));
    }

    @Override
    public Map<String, Object> selectOneByEqual(DataMap dataMap, Map<String, Object> map) {
        JudgesNull(dataMap.getTableName(), "tableName can not be null!");
        Condition condition = equal(dataMap, map);
        return tableMapper.userSqlByOne(condition.getSql());
    }

    @Override
    public Map<String, Object> selectByPk(DataMap dataMap) {
        JudgesNull(dataMap.getTableName(), "tableName can not be null!");
        JudgesNull(dataMap.getPkName(), "pkName can not be null!");
        JudgesNull(dataMap.getPkValue(), "pkValue can not be null!");
        Condition condition = Condition.creatCriteria(dataMap).build();
        condition = condition.toCreatCriteria().andEqual(dataMap.getPkName(), dataMap.getPkValue()).build();
        return tableMapper.userSqlByOne(condition.getSql());
    }

    @Override
    public Map<String, Object> selectByPk(OsSysTable osSysTable, Object pkValue) {
        JudgesNull(osSysTable.getTableName(), "tableName can not be null!");
        JudgesNull(osSysTable.getTablePk(), "pkName can not be null!");
        JudgesNull(pkValue, "pkValue can not be null!");
        Condition condition = Condition.creatCriteria(DataMap.builder().sysOsTable(osSysTable).pkValue(pkValue).build()).build();
        condition = condition.toCreatCriteria().andEqual(osSysTable.getTablePk(), pkValue).build();
        return tableMapper.userSqlByOne(condition.getSql());
    }

    @Override
    public Map<String, Object> selectByPk(String tableName, String pkName, Object pkValue) {
        JudgesNull(tableName, "tableName can not be null!");
        JudgesNull(pkName, "pkName can not be null!");
        JudgesNull(pkValue, "pkValue can not be null!");
        Condition condition = Condition.creatCriteria(DataMap.builder().tableName(tableName).pkName(pkName).pkValue(pkValue).build()).build();
        condition = condition.toCreatCriteria().andEqual(pkName, pkValue).build();
        return tableMapper.userSqlByOne(condition.getSql());
    }

    @Override
    public List<Map<String, Object>> selectByCondition(Condition condition) {
        return tableMapper.useSql(condition.getSql());
    }

    @Override
    public List<Map<String, Object>> selectByCondition(DataMap dataMap, Condition condition) {
        JudgesNull(dataMap.getTableName(), "tableName can not be null!");
        return tableMapper.useSql(condition.toCreatCriteria(dataMap).build().getSql());
    }

    @Override
    public List<Map<String, Object>> selectByCondition(String tableName, Condition condition) {
        JudgesNull(tableName, "tableName can not be null!");
        return tableMapper.useSql(condition.toCreatCriteria(DataMap.builder().tableName(tableName).build()).build().getSql());
    }

    @Override
    public List<Map<String, Object>> selectByCondition(String tableName, List<String> fieldList, Condition condition) {
        JudgesNull(tableName, "tableName can not be null!");
        return tableMapper.useSql(condition
                .toCreatCriteria(DataMap.builder().tableName(tableName).fieldList(fieldList).build())
                .build()
                .getSql());
    }

    @Override
    public List<Map<String, Object>> selectByCondition(String tableName, String fieldList, Condition condition) {
        JudgesNull(tableName, "tableName can not be null!");
        return tableMapper.useSql(condition
                .toCreatCriteria(DataMap.builder().tableName(tableName).fields(fieldList).build())
                .build()
                .getSql());
    }

    @Override
    public PageInfo<Map<String, Object>> selectByCondition(Condition condition, WebPageInfo webPageInfo) {
        MyPageHelper.start(webPageInfo);
        return new PageInfo<>(tableMapper.useSql(condition.getSql()));
    }

    @Override
    public PageInfo<Map<String, Object>> selectByCondition(DataMap dataMap, Condition condition, WebPageInfo webPageInfo) {
        JudgesNull(dataMap.getTableName(), "tableName can not be null!");
        MyPageHelper.start(webPageInfo);
        condition = condition.toCreatCriteria(dataMap).build();
        return new PageInfo<>(tableMapper.useSql(condition.getSql()));
    }

    @Override
    public PageInfo<Map<String, Object>> selectByCondition(String tableName, Condition condition, WebPageInfo webPageInfo) {
        JudgesNull(tableName, "tableName can not be null!");
        MyPageHelper.start(webPageInfo);
        condition = condition.toCreatCriteria(DataMap.builder().tableName(tableName).build()).build();
        return new PageInfo<>(tableMapper.useSql(condition.getSql()));
    }

    @Override
    public PageInfo<Map<String, Object>> selectByCondition(String tableName, List<String> fieldList, Condition condition, WebPageInfo webPageInfo) {
        JudgesNull(tableName, "tableName can not be null!");
        MyPageHelper.start(webPageInfo);
        condition = condition.toCreatCriteria(DataMap.builder().tableName(tableName).fieldList(fieldList).build()).build();
        return new PageInfo<>(tableMapper.useSql(condition.getSql()));
    }

    @Override
    public PageInfo<Map<String, Object>> selectByCondition(String tableName, String fieldList, Condition condition, WebPageInfo webPageInfo) {
        JudgesNull(tableName, "tableName can not be null!");
        MyPageHelper.start(webPageInfo);
        condition = condition.toCreatCriteria(DataMap.builder().tableName(tableName).fields(fieldList).build()).build();
        return new PageInfo<>(tableMapper.useSql(condition.getSql()));
    }

    @Override
    public Map<String, Object> selectOneByCondition(DataMap dataMap, Condition condition) {
        JudgesNull(dataMap.getTableName(), "tableName can not be null!");
        return tableMapper.userSqlByOne(condition.toCreatCriteria(dataMap).build().getSql());
    }

    @Override
    public Map<String, Object> selectOneByCondition(String tableName, Condition condition) {
        JudgesNull(tableName, "tableName can not be null!");
        return tableMapper.userSqlByOne(condition.toCreatCriteria(DataMap.builder().tableName(tableName).build()).build().getSql());
    }

    @Override
    public Map<String, Object> selectOneByCondition(String tableName, List<String> fieldList, Condition condition) {
        JudgesNull(tableName, "tableName can not be null!");
        return tableMapper.userSqlByOne(condition.toCreatCriteria(DataMap.builder().tableName(tableName).fieldList(fieldList).build()).build().getSql());
    }

    @Override
    public Map<String, Object> selectOneByCondition(String tableName, String fieldList, Condition condition) {
        JudgesNull(tableName, "tableName can not be null!");
        return tableMapper.userSqlByOne(condition.toCreatCriteria(DataMap.builder().tableName(tableName).fields(fieldList).build()).build().getSql());
    }

    @Override
    public Map<String, Object> selectOneByCondition(Condition condition) {
        return tableMapper.userSqlByOne(condition.getSql());
    }

    @Override
    public List<Map<String, Object>> selectJoinByCondition(String tableName, JoinCondition joinCondition, Condition condition) {
        JudgesNull(tableName, "tableName can not be null!");
        SelectCondition selectJoinBuilder = SelectCondition
                .joinBuilder(tableName)
                .join(joinCondition).build();
        return tableMapper.useSql(condition.toCreatCriteria(selectJoinBuilder).build().getSql());
    }

    @Override
    public List<Map<String, Object>> selectJoinByCondition(String tableName, List<JoinCondition> joinCondition, Condition condition) {
        JudgesNull(tableName, "tableName can not be null!");
        SelectCondition selectJoinBuilder = SelectCondition
                .joinBuilder(tableName)
                .join(joinCondition).build();
        return tableMapper.useSql(condition.toCreatCriteria(selectJoinBuilder).build().getSql());
    }

    @Override
    public List<Map<String, Object>> selectLeftJoinByCondition(String tableName, JoinCondition joinCondition, Condition condition) {
        JudgesNull(tableName, "tableName can not be null!");
        SelectCondition selectJoinBuilder = SelectCondition
                .joinBuilder(tableName)
                .leftJoin(joinCondition).build();
        return tableMapper.useSql(condition.toCreatCriteria(selectJoinBuilder).build().getSql());
    }

    @Override
    public List<Map<String, Object>> selectLeftJoinByCondition(String tableName, List<JoinCondition> joinCondition, Condition condition) {
        JudgesNull(tableName, "tableName can not be null!");
        SelectCondition selectJoinBuilder = SelectCondition
                .joinBuilder(tableName)
                .leftJoin(joinCondition).build();
        return tableMapper.useSql(condition.toCreatCriteria(selectJoinBuilder).build().getSql());
    }

    @Override
    public List<Map<String, Object>> selectRightJoinByCondition(String tableName, JoinCondition joinCondition, Condition condition) {
        JudgesNull(tableName, "tableName can not be null!");
        SelectCondition selectJoinBuilder = SelectCondition
                .joinBuilder(tableName)
                .rightJoin(joinCondition).build();
        return tableMapper.useSql(condition.toCreatCriteria(selectJoinBuilder).build().getSql());
    }

    @Override
    public List<Map<String, Object>> selectRightJoinByCondition(String tableName, List<JoinCondition> joinCondition, Condition condition) {
        JudgesNull(tableName, "tableName can not be null!");
        SelectCondition selectJoinBuilder = SelectCondition
                .joinBuilder(tableName)
                .rightJoin(joinCondition).build();
        return tableMapper.useSql(condition.toCreatCriteria(selectJoinBuilder).build().getSql());
    }

    @Override
    public List<Map<String, Object>> selectionByCondition(SelectCondition selectCondition, Condition condition) {
        return tableMapper.useSql(condition.toCreatCriteria(selectCondition).build().getSql());
    }

    @Override
    public List<Map<String, Object>> selectSql(String sql) {
        return tableMapper.useSql(sql);
    }

    @Override
    public PageInfo<Map<String, Object>> selectSqlByPage(String sql, WebPageInfo webPageInfo) {
        MyPageHelper.start(webPageInfo);
        return new PageInfo<>(tableMapper.useSql(sql));
    }

    @Override
    public Map<String, Object> selectOneSql(String sql) {
        return tableMapper.userSqlByOne(sql);
    }

    public void JudgesNull(Object object, String str) {
        if (object == null) {
            throw new BaseMapperException(str);
        }
    }

    private Object getSequence(String tableName, String pkName) {
        Object id;
        try {
            id = tableMapper.getSequence(tableName);
        } catch (Exception e) {
            MyPageHelper.start(WebPageInfo.builder().pageNum(1).pageSize(1).order(WebPageInfo.DESC).sortField(pkName).build());
            DataMap dataMap = DataMap.builder().tableName(tableName).pkName(pkName).fields(pkName).build();
            Condition condition = Condition.creatCriteria(dataMap).build();
            Map<String, Object> map = selectOneByCondition(condition);
            tableMapper.createSequence(tableName, map.get(pkName));
            id = tableMapper.getSequence(tableName);
        }
        return Long.parseLong(id.toString())+1L;
    }
}
