package service

import (
	"errors"

	"be.ems/features/sys_config/model"
	"be.ems/lib/core/cache"
	"be.ems/lib/core/constants/cachekey"
)

// 实例化服务层 ServiceSysConfig 结构体
var NewServiceSysConfig = &ServiceSysConfig{
	sysConfigRepository: NewRepoSysConfig,
}

// ServiceSysConfig 参数配置 服务层处理
type ServiceSysConfig struct {
	// 参数配置表
	sysConfigRepository *RepoSysConfig
}

// SelectDictDataPage 分页查询参数配置列表数据
func (r *ServiceSysConfig) SelectConfigPage(query map[string]any) map[string]any {
	return r.sysConfigRepository.SelectConfigPage(query)
}

// SelectConfigList 查询参数配置列表
func (r *ServiceSysConfig) SelectConfigList(sysConfig model.SysConfig) []model.SysConfig {
	return r.sysConfigRepository.SelectConfigList(sysConfig)
}

// SelectConfigValueByKey 通过参数键名查询参数键值
func (r *ServiceSysConfig) SelectConfigValueByKey(configKey string) string {
	cacheKey := r.getCacheKey(configKey)
	// 从缓存中读取
	cacheValue, ok := cache.GetLocal(cacheKey)
	if cacheValue != nil && ok {
		return cacheValue.(string)
	}
	// 无缓存时读取数据放入缓存中
	configValue := r.sysConfigRepository.SelectConfigValueByKey(configKey)
	if configValue != "" {
		cache.SetLocal(cacheKey, configValue)
		return configValue
	}
	return ""
}

// SelectConfigById 通过配置ID查询参数配置信息
func (r *ServiceSysConfig) SelectConfigById(configId string) model.SysConfig {
	if configId == "" {
		return model.SysConfig{}
	}
	configs := r.sysConfigRepository.SelectConfigByIds([]string{configId})
	if len(configs) > 0 {
		return configs[0]
	}
	return model.SysConfig{}
}

// CheckUniqueConfigKey 校验参数键名是否唯一
func (r *ServiceSysConfig) CheckUniqueConfigKey(configKey, configId string) bool {
	uniqueId := r.sysConfigRepository.CheckUniqueConfig(model.SysConfig{
		ConfigKey: configKey,
	})
	if uniqueId == configId {
		return true
	}
	return uniqueId == ""
}

// InsertConfig 新增参数配置
func (r *ServiceSysConfig) InsertConfig(sysConfig model.SysConfig) string {
	configId := r.sysConfigRepository.InsertConfig(sysConfig)
	if configId != "" {
		r.loadingConfigCache(sysConfig.ConfigKey)
	}
	return configId
}

// UpdateConfig 修改参数配置
func (r *ServiceSysConfig) UpdateConfig(sysConfig model.SysConfig) int64 {
	rows := r.sysConfigRepository.UpdateConfig(sysConfig)
	if rows > 0 {
		r.loadingConfigCache(sysConfig.ConfigKey)
	}
	return rows
}

// DeleteConfigByIds 批量删除参数配置信息
func (r *ServiceSysConfig) DeleteConfigByIds(configIds []string) (int64, error) {
	// 检查是否存在
	configs := r.sysConfigRepository.SelectConfigByIds(configIds)
	if len(configs) <= 0 {
		return 0, errors.New("does not have permission to access parameter configuration data")
	}
	for _, config := range configs {
		// 检查是否为内置参数
		if config.ConfigType == "Y" {
			return 0, errors.New(config.ConfigID + " Configuration parameters are built-in parameters and their deletion is prohibited!")
		}
		// 清除缓存
		r.clearConfigCache(config.ConfigKey)
	}
	if len(configs) == len(configIds) {
		rows := r.sysConfigRepository.DeleteConfigByIds(configIds)
		return rows, nil
	}
	return 0, errors.New("failed to delete parameter configuration information")
}

// ResetConfigCache 重置参数缓存数据
func (r *ServiceSysConfig) ResetConfigCache() {
	r.clearConfigCache("*")
	r.loadingConfigCache("*")
}

// getCacheKey 组装缓存key
func (r *ServiceSysConfig) getCacheKey(configKey string) string {
	return cachekey.SYS_CONFIG_KEY + configKey
}

// loadingConfigCache 加载参数缓存数据
func (r *ServiceSysConfig) loadingConfigCache(configKey string) {
	// 查询全部参数
	if configKey == "*" {
		sysConfigs := r.SelectConfigList(model.SysConfig{})
		for _, v := range sysConfigs {
			key := r.getCacheKey(v.ConfigKey)
			cache.DeleteLocal(key)
			cache.SetLocal(key, v.ConfigValue)
		}
		return
	}
	// 指定参数
	if configKey != "" {
		cacheValue := r.sysConfigRepository.SelectConfigValueByKey(configKey)
		if cacheValue != "" {
			key := r.getCacheKey(configKey)
			cache.DeleteLocal(key)
			cache.SetLocal(key, cacheValue)
		}
		return
	}
}

// clearConfigCache 清空参数缓存数据
func (r *ServiceSysConfig) clearConfigCache(configKey string) bool {
	key := r.getCacheKey(configKey)
	keys := cache.GetLocalKeys(key)
	for _, v := range keys {
		cache.DeleteLocal(v)
	}
	return len(keys) > 0
}
