package com.zioinfo.kintex.config;

import com.zioinfo.kintex.auth.AuthProperties;
import com.zioinfo.kintex.security.SecurityPolicyProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * B12 — 운영 시크릿 fail-fast. 운영 프로파일에서 JWT 서명 키/OTP 암호화 키가 <b>개발 폴백</b>이거나
 * 미주입이면 컨텍스트 초기화 단계에서 기동을 중단한다(개발 폴백 값의 운영 유입 차단).
 * 개발 프로파일에서는 경고만 남긴다(로컬 편의 유지).
 *
 * <p>보안 불변(계약 §0-3): 시크릿 <b>값</b>은 로그·예외 메시지에 절대 담지 않는다 — 항목명과 조치만 노출한다.
 * 운영 판정: 활성 프로파일에 {@code prod} 포함 또는 {@code kintex.security.enforce-secrets=true}.
 */
@Component
public class SecretStartupValidator implements InitializingBean {

    private static final Logger log = LoggerFactory.getLogger(SecretStartupValidator.class);

    /** application.yml 개발 폴백 접두어(env 미주입 시 주입되는 값). */
    private static final String DEV_JWT_PREFIX = "CHANGE_ME_DEV_ONLY";

    private final Environment env;
    private final AuthProperties authProperties;
    private final SecurityPolicyProperties securityProperties;

    public SecretStartupValidator(Environment env, AuthProperties authProperties,
                                  SecurityPolicyProperties securityProperties) {
        this.env = env;
        this.authProperties = authProperties;
        this.securityProperties = securityProperties;
    }

    @Override
    public void afterPropertiesSet() {
        boolean production = isProduction();

        boolean jwtWeak = isBlank(authProperties.getJwtSecret())
                || authProperties.getJwtSecret().startsWith(DEV_JWT_PREFIX);
        boolean otpKeyMissing = isBlank(securityProperties.getOtp().getEncKey());

        if (production) {
            if (jwtWeak) {
                throw new IllegalStateException(
                        "운영 기동 중단(fail-fast): JWT_SECRET 이 미주입 또는 개발 폴백값입니다. "
                                + "최소 32바이트 시크릿을 환경변수 JWT_SECRET 로 주입하세요.");
            }
            if (otpKeyMissing) {
                throw new IllegalStateException(
                        "운영 기동 중단(fail-fast): KINTEX_OTP_ENC_KEY(OTP AES-256-GCM 키)가 미주입입니다. "
                                + "base64 32바이트 키를 환경변수 KINTEX_OTP_ENC_KEY 로 주입하세요.");
            }
            log.info("[security] 운영 시크릿 검증 통과 — JWT_SECRET·KINTEX_OTP_ENC_KEY 주입 확인.");
        } else {
            if (jwtWeak) {
                log.warn("[security] JWT_SECRET 이 개발 폴백/미주입 상태입니다 — 운영 배포 전 env 주입 필수(운영 프로파일은 fail-fast).");
            }
            if (otpKeyMissing) {
                log.warn("[security] KINTEX_OTP_ENC_KEY 미주입 — 개발 파생키 사용 중(운영 프로파일은 fail-fast).");
            }
        }
    }

    /** 활성 프로파일에 prod 포함 또는 명시 강제 플래그. */
    private boolean isProduction() {
        if (Boolean.parseBoolean(env.getProperty("kintex.security.enforce-secrets", "false"))) {
            return true;
        }
        return Arrays.stream(env.getActiveProfiles())
                .anyMatch(p -> p != null && p.toLowerCase().contains("prod"));
    }

    private static boolean isBlank(String s) {
        return s == null || s.isBlank();
    }
}
