package config

import (
	"log/slog"
	"os"
	"strconv"
)

// Config 持有 api-gateway 运行时配置。
// P2 起 JWT 验签改 RS256（IAM 签发，Gateway 用 JWKS 公钥校验），
// JWTSecret 仅在 DevMode 下作为 mock 密钥保留。
type Config struct {
	Port              string
	JWKSURL           string // RS256 公钥端点（IAM GET /.well-known/jwks.json）
	JWTSecret         string // DevMode 下 mock 用（生产不再使用 HS256）
	JWTIssuer         string
	JWTAudience       string
	CORSOrigins       string
	ClassesServiceURL string
	IamServiceURL     string
	TeacherBffURL     string
	StudentBffURL     string
	ParentBffURL      string
	CoreEduServiceURL string
	ContentServiceURL string
	DataAnaServiceURL string
	MsgServiceURL     string
	AiServiceURL      string
	OTLPEndpoint      string
	LogLevel          string
	DevMode           bool
	Env               string // 部署环境标识：production / development（W7 防护用）
}

// devJWTSecret 是 DevMode 下的默认 JWT 密钥（仅用于本地联调，生产必须关闭 DevMode）
const devJWTSecret = "p1-dev-secret-change-in-production"

// Load 从环境变量加载配置。
//
// W7 生产防护：DevMode=true 且 ENV=production 时 panic 拒绝启动，
// 避免 dev-token 旁路鉴权被误开到生产环境。
// P2 起 RS256：非 DevMode 下要求 IAM_JWKS_URL（JWKS 公钥端点），
// JWT_SECRET 不再是生产必填（仅 DevMode mock 用）。
func Load() *Config {
	devMode := getEnvBool("DEV_MODE", false)
	env := getEnv("ENV", "development")

	// W7 生产防护：DevMode 旁路仅允许非生产环境
	if devMode && env == "production" {
		panic("DEV_MODE=true is not allowed in production (ENV=production)")
	}

	jwtSecret := getEnv("JWT_SECRET", "")
	if jwtSecret == "" && devMode {
		slog.Warn("JWT_SECRET not set, using dev default (DEV_MODE=true)")
		jwtSecret = devJWTSecret
	}

	// 非 DevMode 下要求 JWKS URL（RS256 验签）
	jwksURL := getEnv("IAM_JWKS_URL", "http://localhost:3002/.well-known/jwks.json")
	if !devMode && jwksURL == "" {
		panic("IAM_JWKS_URL must be set in non-dev mode (RS256 JWT verification)")
	}

	slog.Info("config loaded",
		"env", env,
		"dev_mode", devMode,
		"jwks_url", jwksURL,
	)

	return &Config{
		Port:              getEnv("API_GATEWAY_PORT", "8080"),
		JWKSURL:           jwksURL,
		JWTSecret:         jwtSecret,
		JWTIssuer:         getEnv("JWT_ISSUER", "next-edu-cloud"),
		JWTAudience:       getEnv("JWT_AUDIENCE", "next-edu-cloud"),
		CORSOrigins:       getEnv("CORS_ORIGINS", ""),
		ClassesServiceURL: getEnv("CLASSES_SERVICE_URL", "http://localhost:3001"),
		IamServiceURL:     getEnv("IAM_SERVICE_URL", "http://localhost:3002"),
		TeacherBffURL:     getEnv("TEACHER_BFF_URL", "http://localhost:3003"),
		StudentBffURL:     getEnv("STUDENT_BFF_URL", "http://localhost:3009"),
		ParentBffURL:      getEnv("PARENT_BFF_URL", "http://localhost:3010"),
		CoreEduServiceURL: getEnv("CORE_EDU_SERVICE_URL", "http://localhost:3004"),
		ContentServiceURL: getEnv("CONTENT_SERVICE_URL", "http://localhost:3005"),
		DataAnaServiceURL: getEnv("DATA_ANA_SERVICE_URL", "http://localhost:3006"),
		MsgServiceURL:     getEnv("MSG_SERVICE_URL", "http://localhost:3007"),
		AiServiceURL:      getEnv("AI_SERVICE_URL", "http://localhost:3008"),
		OTLPEndpoint:      getEnv("OTEL_EXPORTER_OTLP_ENDPOINT", "http://localhost:4318"),
		LogLevel:          getEnv("LOG_LEVEL", "info"),
		DevMode:           devMode,
		Env:               env,
	}
}

// getEnv 读取环境变量，缺失或空字符串时返回 fallback
func getEnv(key, fallback string) string {
	if v := os.Getenv(key); v != "" {
		return v
	}
	return fallback
}

// getEnvBool 读取环境变量并解析为 bool，缺失或解析失败时返回 fallback
func getEnvBool(key string, fallback bool) bool {
	if v := os.Getenv(key); v != "" {
		if b, err := strconv.ParseBool(v); err == nil {
			return b
		}
	}
	return fallback
}
