package com.yfd.platform.modules.config.service;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.convert.ConvertException;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import com.yfd.platform.constant.SystemConfigConstant;
import com.yfd.platform.modules.config.event.ISystemConfigModifyHandler;
import com.yfd.platform.modules.config.mapper.SystemConfigMapper;
import com.yfd.platform.modules.config.model.dto.SystemConfigDTO;
import com.yfd.platform.modules.config.model.entity.SystemConfig;
import com.yfd.platform.utils.EnumConvertUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Optional;

/**
 * 系统设置 Service
 *
 * @author zhengsl
 */
@Slf4j
@Service
@CacheConfig(cacheNames = "systemConfig")
public class SystemConfigService {

    public static final String CACHE_NAME = "systemConfig";

    private static final String DEFAULT_USERNAME = "admin";

    private static final String DEFAULT_PASSWORD = "123456";
//    private static final String CACHE_NAME = "systemConfig";

    @Resource
    private SystemConfigMapper systemConfigMapper;

//    @Resource
//    private SystemConfigService systemConfigService;

    @Resource
    private CacheManager cacheManager;

    @Resource
    private ISystemConfigModifyHandler systemConfigModifyHandler;

    private final Class<SystemConfigDTO> systemConfigClazz = SystemConfigDTO.class;


    /**
     * 获取系统设置, 如果缓存中有, 则去缓存取, 没有则查询数据库并写入到缓存中.
     *
     * @return  系统设置
     */
    @Cacheable(key = "'dto'")
    public SystemConfigDTO getSystemConfig() {
        SystemConfigDTO systemConfigDTO = new SystemConfigDTO();
        List<SystemConfig> systemConfigList = systemConfigMapper.findAll();

        for (SystemConfig systemConfig : systemConfigList) {
            String key = systemConfig.getName();

            try {
                Field field = systemConfigClazz.getDeclaredField(key);
                field.setAccessible(true);
                String strVal = systemConfig.getValue();
                Class<?> fieldType = field.getType();

                Object convertVal;
                if (EnumUtil.isEnum(fieldType)) {
                    convertVal = EnumConvertUtils.convertStrToEnum(fieldType, strVal);
                } else {
                    convertVal = Convert.convert(fieldType, strVal);
                }
                field.set(systemConfigDTO, convertVal);
            } catch (NoSuchFieldException | IllegalAccessException | ConvertException e) {
                log.error("通过反射, 将字段 {} 注入 SystemConfigDTO 时出现异常:", key, e);
            }
        }

        return systemConfigDTO;
    }



    /**
     * 获取 RSA Hex 格式密钥
     *
     * @return  RSA Hex 格式密钥
     */
    public synchronized String getRsaHexKeyOrGenerate() {
        SystemConfigDTO systemConfigDTO = this.getSystemConfig();
        String rsaHexKey = systemConfigDTO.getRsaHexKey();
        if (StrUtil.isEmpty(rsaHexKey)) {
            byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded();
            rsaHexKey = HexUtil.encodeHexStr(key);

            SystemConfig loginVerifyModeConfig = systemConfigMapper.findByName(SystemConfigConstant.RSA_HEX_KEY);
            loginVerifyModeConfig.setValue(rsaHexKey);
            systemConfigMapper.updateById(loginVerifyModeConfig);
            systemConfigDTO.setRsaHexKey(rsaHexKey);

            Cache cache = cacheManager.getCache(CACHE_NAME);
            Optional.ofNullable(cache).ifPresent(cache1 -> cache1.put("dto", systemConfigDTO));
        }
        return rsaHexKey;
    }


    /**
     * 获取系统是否已初始化
     *
     * @return  管理员名称
     */
    public Boolean getSystemIsInstalled() {
        return this.getSystemConfig().getInstalled();
    }


    /**
     * 获取后端站点域名
     *
     * @return  后端站点域名
     */
    public String getDomain() {
        SystemConfigDTO systemConfigDTO = this.getSystemConfig();
        return systemConfigDTO.getDomain();
    }


    /**
     * 获取前端站点域名
     *
     * @return  前端站点域名
     */
    public String getFrontDomain() {
        SystemConfigDTO systemConfigDTO = this.getSystemConfig();
        return systemConfigDTO.getFrontDomain();
    }


    /**
     * 获取实际的前端站点域名
     *
     * @return  实际的前端站点域名
     */
    public String getRealFrontDomain() {
        SystemConfigDTO systemConfigDTO = this.getSystemConfig();
        return StrUtil.firstNonNull(systemConfigDTO.getFrontDomain(), systemConfigDTO.getDomain());
    }


    /**
     * 获取前端地址下的 403 页面地址.
     *
     * @return 前端地址下的 403 页面地址.
     *
     */
    public String getForbiddenUrl() {
        return getRealFrontDomain() + "/403";
    }

}
