package com.ruoyi.crypto.config;

import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * 密码改造全局配置，绑定 {@code application.yml} 中 {@code crypto.*} 节点。
 * <p>
 * 一期主要供 {@link com.ruoyi.crypto.service.impl.StubCryptoServiceImpl} 读取密钥索引与 HSM 连接信息；
 * 二期起 MyBatis 加解密拦截器、完整性巡检等模块同样依赖本配置。
 * </p>
 *
 * @see doc/密码改造/配置与接口说明.md
 */
@ConfigurationProperties(prefix = "crypto")
public class CryptoProperties
{
    /**
     * 密码改造总开关。
     * false 时业务层可跳过加解密（仅建议迁移双写期使用）；生产开启篡改保护后不建议关闭。
     */
    private boolean enabled = true;

    /** 密码机（HSM）连接与厂商标识 */
    private Hsm hsm = new Hsm();

    /** 按数据分类划分的密钥索引，对应密码机内槽位，非密钥本身 */
    private Keys keys = new Keys();

    public boolean isEnabled()
    {
        return enabled;
    }

    public void setEnabled(boolean enabled)
    {
        this.enabled = enabled;
    }

    public Hsm getHsm()
    {
        return hsm;
    }

    public void setHsm(Hsm hsm)
    {
        this.hsm = hsm;
    }

    public Keys getKeys()
    {
        return keys;
    }

    public void setKeys(Keys keys)
    {
        this.keys = keys;
    }

    /** 密码机连接参数（生产由运维填写 IP:端口、厂商 SDK 类型） */
    public static class Hsm
    {
        /** stub=本模块 Stub 实现；vendor-sdk=对接真实密码机 */
        private String provider = "stub";

        /** 主备密码机地址列表，Stub 实现用于派生密钥种子 */
        private List<String> hosts = new ArrayList<>();

        private int connectTimeoutMs = 5000;

        private int readTimeoutMs = 10000;

        /** 连接池大小，压测阶段按密码机性能调整 */
        private int poolSize = 20;

        public String getProvider()
        {
            return provider;
        }

        public void setProvider(String provider)
        {
            this.provider = provider;
        }

        public List<String> getHosts()
        {
            return hosts;
        }

        public void setHosts(List<String> hosts)
        {
            this.hosts = hosts;
        }

        public int getConnectTimeoutMs()
        {
            return connectTimeoutMs;
        }

        public void setConnectTimeoutMs(int connectTimeoutMs)
        {
            this.connectTimeoutMs = connectTimeoutMs;
        }

        public int getReadTimeoutMs()
        {
            return readTimeoutMs;
        }

        public void setReadTimeoutMs(int readTimeoutMs)
        {
            this.readTimeoutMs = readTimeoutMs;
        }

        public int getPoolSize()
        {
            return poolSize;
        }

        public void setPoolSize(int poolSize)
        {
            this.poolSize = poolSize;
        }
    }

    /**
     * 密钥索引分组，与 {@link com.ruoyi.crypto.enums.CryptoDataType} 一一对应。
     * YAML 示例：{@code crypto.keys.personal.hmac-index: 11}
     */
    public static class Keys
    {
        /** 身份鉴别数据：口令、证书序列号等 */
        private KeyPair credential = new KeyPair();

        /** 个人信息：手机、邮箱、姓名等 */
        private KeyPair personal = new KeyPair();

        /** 权限信息：用户、角色、菜单关联（一般仅 HMAC） */
        private KeyPair permission = new KeyPair();

        /** 操作/登录日志 */
        private KeyPair log = new KeyPair();

        /** 产业业务表敏感字段 */
        private KeyPair business = new KeyPair();

        public KeyPair getCredential()
        {
            return credential;
        }

        public void setCredential(KeyPair credential)
        {
            this.credential = credential;
        }

        public KeyPair getPersonal()
        {
            return personal;
        }

        public void setPersonal(KeyPair personal)
        {
            this.personal = personal;
        }

        public KeyPair getPermission()
        {
            return permission;
        }

        public void setPermission(KeyPair permission)
        {
            this.permission = permission;
        }

        public KeyPair getLog()
        {
            return log;
        }

        public void setLog(KeyPair log)
        {
            this.log = log;
        }

        public KeyPair getBusiness()
        {
            return business;
        }

        public void setBusiness(KeyPair business)
        {
            this.business = business;
        }

        public KeyPair resolve(CryptoDataTypeKey dataType)
        {
            switch (dataType)
            {
                case CREDENTIAL:
                    return credential;
                case PERSONAL:
                    return personal;
                case PERMISSION:
                    return permission;
                case LOG:
                    return log;
                case BUSINESS:
                    return business;
                default:
                    return new KeyPair();
            }
        }
    }

    /** 单组数据类型对应的 HMAC / SM4 密钥槽位号 */
    public static class KeyPair
    {
        private int hmacIndex = 10;

        private int sm4Index = 1;

        public int getHmacIndex()
        {
            return hmacIndex;
        }

        public void setHmacIndex(int hmacIndex)
        {
            this.hmacIndex = hmacIndex;
        }

        public int getSm4Index()
        {
            return sm4Index;
        }

        public void setSm4Index(int sm4Index)
        {
            this.sm4Index = sm4Index;
        }
    }

    /** 与 YAML 中 keys.credential 等键名对应 */
    public enum CryptoDataTypeKey
    {
        CREDENTIAL("credential"),
        PERSONAL("personal"),
        PERMISSION("permission"),
        LOG("log"),
        BUSINESS("business");

        private final String configKey;

        CryptoDataTypeKey(String configKey)
        {
            this.configKey = configKey;
        }

        public String configKey()
        {
            return configKey;
        }

        public static CryptoDataTypeKey from(com.ruoyi.crypto.enums.CryptoDataType dataType)
        {
            return CryptoDataTypeKey.valueOf(dataType.name());
        }
    }
}
