package com.ruoyi.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.solon.service.impl.ServiceImpl;
import com.ruoyi.common.constants.CacheConstant;
import com.ruoyi.common.enums.DictEnum;
import com.ruoyi.common.utils.RedisUtil;
import com.ruoyi.common.web.exception.ServiceException;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.mapper.SysConfigMapper;
import com.ruoyi.system.service.ISysConfigService;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.data.annotation.Transaction;

import java.util.List;

/**
 * 系统参数配置 服务层实现
 * @author ruoyi
 */
@Component
public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper, SysConfig> implements ISysConfigService {

    @Inject
    SysConfigMapper sysConfigMapper;

    @Inject
    RedisUtil redisUtil;

    /**
     * 根据键名查询参数配置信息
     * @param configKey 参数key
     * @return
     */
    @Override
    public String selectConfigByKey(String configKey) {
        String cacheKey = getCacheKey(configKey);
        String configValue = redisUtil.getCacheObject(cacheKey);
        if (StrUtil.isNotEmpty(configValue)) {
            return configValue;
        }
        QueryWrapper qw = QueryWrapper.create();
        qw.where(SysConfig::getConfigKey).eq(configKey);
        SysConfig sysConfig = sysConfigMapper.selectOneByQuery(qw);
        if (ObjectUtil.isNotNull(sysConfig)) {
            redisUtil.setCacheObject(cacheKey, sysConfig.getConfigValue());
            return sysConfig.getConfigValue();
        }
        return StrUtil.EMPTY;
    }

    /**
     * 新增系统参数配置
     * @param sysConfig
     * @return
     */
    @Override
    public int add(SysConfig sysConfig) {
        if (!checkConfigKeyUnique(sysConfig)) {
            throw new ServiceException("参数键名已存在");
        }
        int row = sysConfigMapper.insert(sysConfig);
        if (row > 0) {
            redisUtil.setCacheObject(getCacheKey(sysConfig.getConfigKey()), sysConfig.getConfigValue());
        }
        return row;
    }

    /**
     * 修改系统参数配置
     * @param sysConfig
     * @return
     */
    @Transaction
    @Override
    public int edit(SysConfig sysConfig) {
        if (!checkConfigKeyUnique(sysConfig)) {
            throw new ServiceException("参数键名已存在");
        }
        SysConfig oldConfig = sysConfigMapper.selectOneById(sysConfig.getConfigId());
        // 如果键名都改了，删除旧键名的缓存
        if(!oldConfig.getConfigKey().equals(sysConfig.getConfigKey())) {
            redisUtil.deleteCacheObject(getCacheKey(oldConfig.getConfigKey()));
        }
        int row = sysConfigMapper.update(sysConfig);
        if (row > 0) {
            redisUtil.setCacheObject(getCacheKey(sysConfig.getConfigKey()), sysConfig.getConfigValue());
        }
        return row;
    }

    /**
     * 删除系统参数配置
     * @param dictIds
     * @return
     */
    @Override
    public void delete(List<Long> dictIds) {
        List<SysConfig> sysConfigs = sysConfigMapper.selectListByIds(dictIds);
        for (SysConfig sysConfig : sysConfigs) {
            if(DictEnum.COMMON_YES_NO.YES.getValue().equals(sysConfig.getConfigType())) {
                throw new ServiceException("内置参数不能删除");
            }
            sysConfigMapper.deleteById(sysConfig.getConfigId());
            redisUtil.deleteCacheObject(getCacheKey(sysConfig.getConfigKey()));
        }
    }

    /**
     * 刷新系统参数配置缓存
     */
    @Override
    public void loadingConfigCache() {
        List<SysConfig> sysConfigs = sysConfigMapper.selectAll();
        redisUtil.deleteCacheObjectAll(getCacheKey("*"));
        for (SysConfig sysConfig : sysConfigs) {
            redisUtil.setCacheObject(getCacheKey(sysConfig.getConfigKey()), sysConfig.getConfigValue());
        }
    }

    /**
     * 校验参数键名是否唯一
     * @param sysConfig
     * @return
     */
    private boolean checkConfigKeyUnique(SysConfig sysConfig) {
        long configId = sysConfig.getConfigId() == null ? -1L : sysConfig.getConfigId();
        QueryWrapper qw = QueryWrapper.create();
        qw.and(SysConfig::getConfigKey).eq(sysConfig.getConfigKey());
        qw.limit(1);
        SysConfig sc = sysConfigMapper.selectOneByQuery(qw);
        return ObjectUtil.isNull(sc) || sc.getConfigId() == configId;
    }

    private String getCacheKey(String key) {
        return CacheConstant.SYS_CONFIG_KEY + key;
    }

}
