package com.huimv.employment.config;

import com.alibaba.druid.filter.config.ConfigTools;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * 使用 Druid {@link ConfigTools} 与 {@code spring.datasource.druid.public-key} 解密 Redis 密码。
 * <p>MySQL 密码由 Druid ConfigFilter 在连接池层解密；Redis 需在此提前写入明文到 Environment。</p>
 */
public class DecryptRedisPasswordEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {

    private static final String PUBLIC_KEY = "spring.datasource.druid.public-key";
    private static final String PUBLIC_KEY_ALT = "spring.datasource.druid.publickey";
    private static final String REDIS_PASSWORD = "spring.redis.password";

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        String publicKey = resolvePublicKey(environment);
        if (!StringUtils.hasText(publicKey)) {
            return;
        }

        Map<String, Object> properties = new HashMap<>(4);
        properties.put(PUBLIC_KEY, publicKey);
        properties.put(PUBLIC_KEY_ALT, publicKey);

        String encryptedPassword = environment.getProperty(REDIS_PASSWORD);
        if (StringUtils.hasText(encryptedPassword)) {
            try {
                properties.put(REDIS_PASSWORD, ConfigTools.decrypt(publicKey, encryptedPassword));
            } catch (Exception ex) {
                throw new IllegalStateException("Redis 密码解密失败，请检查 public-key 与密文是否匹配", ex);
            }
        }

        environment.getPropertySources().addFirst(
                new MapPropertySource("decryptedDruidAndRedisPassword", properties));
    }

    private static String resolvePublicKey(ConfigurableEnvironment environment) {
        String publicKey = environment.getProperty(PUBLIC_KEY);
        if (StringUtils.hasText(publicKey)) {
            return publicKey;
        }
        return environment.getProperty(PUBLIC_KEY_ALT);
    }

    @Override
    public int getOrder() {
        // 须在 ConfigDataEnvironmentPostProcessor 加载完 application-{profile}.yml 之后再解密
        return Ordered.LOWEST_PRECEDENCE;
    }
}
