package cn.com.poc.knowledge.rest.impl;

import cn.com.poc.common.domain.database.TableDataResponse;
import cn.com.poc.common.domain.database.TableInfo;
import cn.com.poc.common.utils.Assert;
import cn.com.poc.common.utils.BlContext;
import cn.com.poc.common.utils.DatabaseUtil;
import cn.com.poc.common.utils.StringUtils;
import cn.com.poc.knowledge.cache.DatabaseTableInfoCache;
import cn.com.poc.knowledge.convert.BizKnowledgeDatabaseConvert;
import cn.com.poc.knowledge.dto.*;
import cn.com.poc.knowledge.entity.BizKnowledgeDatabaseEntity;
import cn.com.poc.knowledge.query.KnowledgeDatabaseQueryInfoQueryCondition;
import cn.com.poc.knowledge.query.KnowledgeDatabaseQueryInfoQueryItem;
import cn.com.poc.knowledge.rest.DatabaseRest;
import cn.com.poc.knowledge.service.BizKnowledgeDatabaseService;
import cn.com.poc.support.security.oauth.entity.UserBaseEntity;
import cn.com.yict.framemax.core.exception.BusinessException;
import cn.com.yict.framemax.data.model.PagingInfo;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class DatabaseRestImpl implements DatabaseRest {


    @Resource
    private BizKnowledgeDatabaseService bizKnowledgeDatabaseService;

    @Override
    public BizKnowledgeDatabaseDto create(BizKnowledgeDatabaseDto dto) {
        Assert.notNull(dto, "response can not be null");
        Assert.notBlank(dto.getTitle(), "title can not be blank");
        Assert.notBlank(dto.getDbHost(), "Database Host must not be blank");
        Assert.notBlank(dto.getDbType(), "Database Type must not be blank");
        Assert.notNull(dto.getDbPort(), "Database Port must not be blank");
        Assert.notBlank(dto.getDbName(), "Database Name must not be blank");
        Assert.notBlank(dto.getDbUsername(), "Database Username must not be blank");
        Assert.notBlank(dto.getDbPassword(), "Database Password must not be blank");
        boolean connect = DatabaseUtil.testConnect(dto.getDbHost(), dto.getDbPort(), dto.getDbUsername(), dto.getDbPassword(), dto.getDbName());
        List<TableInfo> tableInfos = DatabaseUtil.getTableInfo(dto.getDbHost(), dto.getDbPort(), dto.getDbUsername(), dto.getDbPassword(), dto.getDbName());
        if (!connect || tableInfos == null) {
            throw new BusinessException("Database connection failed");
        }
        UserBaseEntity userBaseEntity = BlContext.getCurrentUserNotException();
        Long userId = userBaseEntity.getUserId();
        BizKnowledgeDatabaseEntity bizKnowledgeDatabaseEntity = BizKnowledgeDatabaseConvert.dtoToEntity(dto);
        bizKnowledgeDatabaseEntity.setMemberId(userId.intValue());
        BizKnowledgeDatabaseEntity saveEntity = bizKnowledgeDatabaseService.save(bizKnowledgeDatabaseEntity);
        if (saveEntity == null) {
            throw new BusinessException("create database error");
        }
        DatabaseTableInfoCache.updateOrSaveCache(saveEntity.getId().intValue(), tableInfos);
        return BizKnowledgeDatabaseConvert.entityToDto(saveEntity);
    }

    @Override
    public DatabaseTestContentDto testConnection(BizKnowledgeDatabaseDto dto) {
        Assert.notBlank(dto.getDbHost(), "Database Host must not be blank");
        Assert.notNull(dto.getDbPort(), "Database Port must not be blank");
        Assert.notBlank(dto.getDbName(), "Database Name must not be blank");
        Assert.notBlank(dto.getDbUsername(), "Database Username must not be blank");
        Assert.notBlank(dto.getDbPassword(), "Database Password must not be blank");
        boolean connect = DatabaseUtil.testConnect(dto.getDbHost(), dto.getDbPort(), dto.getDbUsername(), dto.getDbPassword(), dto.getDbName());
        DatabaseTestContentDto result = new DatabaseTestContentDto();
        result.setStatus(connect ? "success" : "fail");
        return result;
    }

    @Override
    public BizKnowledgeDatabaseDto get(Integer id) {
        Assert.notNull(id, "id can not be null");
        UserBaseEntity userBaseEntity = BlContext.getCurrentUserNotException();
        Long userId = userBaseEntity.getUserId();

        BizKnowledgeDatabaseEntity bizKnowledgeDatabaseEntity = bizKnowledgeDatabaseService.get(id.longValue());
        if (bizKnowledgeDatabaseEntity == null || (!bizKnowledgeDatabaseEntity.getMemberId().equals(0) && !bizKnowledgeDatabaseEntity.getMemberId().equals(userId.intValue()))) {
            throw new BusinessException("no database found");
        }
        BizKnowledgeDatabaseDto bizKnowledgeDatabaseDto = BizKnowledgeDatabaseConvert.entityToDto(bizKnowledgeDatabaseEntity);
        //获取表信息
        List<TableInfo> tableInfos = DatabaseTableInfoCache.getCache(id);
        if (tableInfos == null) {
            tableInfos = DatabaseUtil.getTableInfo(bizKnowledgeDatabaseEntity.getDbHost(),
                    bizKnowledgeDatabaseEntity.getDbPort(),
                    bizKnowledgeDatabaseEntity.getDbUsername(),
                    bizKnowledgeDatabaseEntity.getDbPassword(),
                    bizKnowledgeDatabaseEntity.getDbName());
            if (tableInfos == null) {
                throw new BusinessException("connection database error");
            }
        }
        bizKnowledgeDatabaseDto.setTableInfos(tableInfos);
        return bizKnowledgeDatabaseDto;
    }

    @Override
    public List<BizKnowledgeDatabaseDto> getByIds(Integer[] ids) {
        Assert.notEmpty(ids, "id can not be null");
        UserBaseEntity userBaseEntity = BlContext.getCurrentUserNotException();
        Long userId = userBaseEntity.getUserId();
        List<BizKnowledgeDatabaseDto> result = new ArrayList<>();
        for (Integer id : ids) {
            BizKnowledgeDatabaseEntity bizKnowledgeDatabaseEntity = bizKnowledgeDatabaseService.get(id.longValue());
            if (bizKnowledgeDatabaseEntity == null || (!bizKnowledgeDatabaseEntity.getMemberId().equals(0)
                    && !bizKnowledgeDatabaseEntity.getMemberId().equals(userId.intValue()))) {
                continue;
            }
            BizKnowledgeDatabaseDto bizKnowledgeDatabaseDto = BizKnowledgeDatabaseConvert.entityToDto(bizKnowledgeDatabaseEntity);
            //获取表信息
            List<TableInfo> tableInfos = DatabaseTableInfoCache.getCache(id);
            if (tableInfos == null) {
                tableInfos = DatabaseUtil.getTableInfo(bizKnowledgeDatabaseEntity.getDbHost(),
                        bizKnowledgeDatabaseEntity.getDbPort(),
                        bizKnowledgeDatabaseEntity.getDbUsername(),
                        bizKnowledgeDatabaseEntity.getDbPassword(),
                        bizKnowledgeDatabaseEntity.getDbName());
                if (tableInfos == null) {
                    continue;
                }
            }
            bizKnowledgeDatabaseDto.setTableInfos(tableInfos);
            result.add(bizKnowledgeDatabaseDto);
        }
        return result;
    }

    @Override
    public List<BizKnowledgeDatabaseDto> getList(KnowledgeDatabaseSearchDto knowledgeDatabaseSearchDto, PagingInfo pagingInfo) {
        UserBaseEntity userBaseEntity = BlContext.getCurrentUserNotException();
        Long userId = userBaseEntity.getUserId();
        KnowledgeDatabaseQueryInfoQueryCondition condition = new KnowledgeDatabaseQueryInfoQueryCondition();
        condition.setMemberId(userId.intValue());
        if (StringUtils.isNotBlank(knowledgeDatabaseSearchDto.getSearch())) {
            condition.setSearch(knowledgeDatabaseSearchDto.getSearch());
        }
        List<KnowledgeDatabaseQueryInfoQueryItem> items = bizKnowledgeDatabaseService.queryKnowledgeDatabaseQueryInfo(condition, pagingInfo);
        List<BizKnowledgeDatabaseDto> result = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(items)) {
            for (KnowledgeDatabaseQueryInfoQueryItem item : items) {
                BizKnowledgeDatabaseDto bizKnowledgeDatabaseDto = BizKnowledgeDatabaseConvert.itemToDto(item);
                List<TableInfo> tableInfos = DatabaseTableInfoCache.getCache(bizKnowledgeDatabaseDto.getId().intValue());
                if (tableInfos == null) {
                    tableInfos = DatabaseUtil.getTableInfo(item.getDbHost(),
                            item.getDbPort(),
                            item.getDbUsername(),
                            item.getDbPassword(),
                            item.getDbName());
                    if (tableInfos == null) {
                        continue;
                    }
                }
                bizKnowledgeDatabaseDto.setTableInfos(tableInfos);
                DatabaseTableInfoCache.updateOrSaveCache(bizKnowledgeDatabaseDto.getId().intValue(), tableInfos);
                result.add(bizKnowledgeDatabaseDto);
            }
        }
        return result;
    }

    @Override
    public boolean delete(Integer id) {
        Assert.notNull(id, "id can not be null");
        UserBaseEntity userBaseEntity = BlContext.getCurrentUserNotException();
        Long userId = userBaseEntity.getUserId();
        BizKnowledgeDatabaseEntity entity = bizKnowledgeDatabaseService.get(id.longValue());
        if (entity == null) {
            return false;
        }
        if (!entity.getMemberId().equals(userId.intValue())) {
            throw new BusinessException("no permission");
        }
        bizKnowledgeDatabaseService.deletedById(id.longValue());
        return true;
    }

    @Override
    public BizKnowledgeDatabaseDto update(BizKnowledgeDatabaseDto dto) {
        Assert.notNull(dto, "response can not be null");
        Assert.notNull(dto.getId(), "id can not be null");

        boolean connect = DatabaseUtil.testConnect(dto.getDbHost(), dto.getDbPort(), dto.getDbUsername(), dto.getDbPassword(), dto.getDbName());
        List<TableInfo> tableInfos = DatabaseUtil.getTableInfo(dto.getDbHost(),
                dto.getDbPort(),
                dto.getDbUsername(),
                dto.getDbPassword(),
                dto.getDbName());

        if (!connect || tableInfos == null) {
            throw new BusinessException("Database connection failed");
        }

        BizKnowledgeDatabaseEntity bizKnowledgeDatabaseEntity = BizKnowledgeDatabaseConvert.dtoToEntity(dto);
        BizKnowledgeDatabaseEntity updateEntity = bizKnowledgeDatabaseService.update(bizKnowledgeDatabaseEntity);
        if (updateEntity == null) {
            throw new BusinessException("update database info error");
        }

        DatabaseTableInfoCache.updateOrSaveCache(updateEntity.getId().intValue(), tableInfos);
        return BizKnowledgeDatabaseConvert.entityToDto(updateEntity);
    }

    @Override
    public List<BizDatabaseTableInfoDto> getTableInfo(Integer id) {
        Assert.notNull(id, "id can not be null");
        UserBaseEntity userBaseEntity = BlContext.getCurrentUserNotException();
        Long userId = userBaseEntity.getUserId();
        BizKnowledgeDatabaseEntity bizKnowledgeDatabaseEntity = bizKnowledgeDatabaseService.get(id.longValue());
        if (bizKnowledgeDatabaseEntity == null || !bizKnowledgeDatabaseEntity.getMemberId().equals(userId.intValue())) {
            throw new BusinessException("no database found");
        }
        List<TableInfo> tableInfos = DatabaseUtil.getTableInfo(bizKnowledgeDatabaseEntity.getDbHost(),
                bizKnowledgeDatabaseEntity.getDbPort(),
                bizKnowledgeDatabaseEntity.getDbUsername(),
                bizKnowledgeDatabaseEntity.getDbPassword(),
                bizKnowledgeDatabaseEntity.getDbName());

        if (CollectionUtils.isEmpty(tableInfos)) {
            throw new BusinessException("connection database error");
        }
        DatabaseTableInfoCache.updateOrSaveCache(id, tableInfos);
        return tableInfos.stream().map(info -> {
            BizDatabaseTableInfoDto dto = new BizDatabaseTableInfoDto();
            dto.setTableName(info.getTABLE_NAME());
            dto.setTableComment(info.getTABLE_COMMENT());
            dto.setTableRows(info.getTABLE_ROWS());
            dto.setTableColumn(info.getTABLE_COLUMN());
            return dto;
        }).collect(Collectors.toList());
    }

    @Override
    public DatabaseTableDataDto getTableData(DatabaseTableDataResponseDto dto, PagingInfo pagingInfo) {
        Assert.notNull(dto.getId(), "id can not be null");
        Assert.notNull(dto.getTable(), "table can not be null");
        UserBaseEntity userBaseEntity = BlContext.getCurrentUserNotException();
        Long userId = userBaseEntity.getUserId();
        BizKnowledgeDatabaseEntity bizKnowledgeDatabaseEntity = bizKnowledgeDatabaseService.get(dto.getId().longValue());
        if (bizKnowledgeDatabaseEntity == null || (!bizKnowledgeDatabaseEntity.getMemberId().equals(0) && !bizKnowledgeDatabaseEntity.getMemberId().equals(userId.intValue()))) {
            throw new BusinessException("no database found");
        }

        TableDataResponse tableDataResponse = DatabaseUtil.getTableData(bizKnowledgeDatabaseEntity.getDbHost(), bizKnowledgeDatabaseEntity.getDbPort(),
                bizKnowledgeDatabaseEntity.getDbUsername(), bizKnowledgeDatabaseEntity.getDbPassword(), bizKnowledgeDatabaseEntity.getDbName(),
                dto.getTable(), pagingInfo.getPageNo(), pagingInfo.getPageSize());
        DatabaseTableDataDto result = new DatabaseTableDataDto();
        BeanUtils.copyProperties(tableDataResponse, result);
        return result;
    }
}