package config

import (
	"net/url"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/joho/godotenv"
)

// Config 全部由环境变量填充（可通过工作目录下 .env.development 或 ENV_FILE 设置，见 Load）。
type Config struct {
	AppEnv     string
	AdminToken string
	AuthAPIURL string
	DatabaseDSN string

	// 进程与对外访问（管理后台「系统状态」展示）
	HTTPListenAddr     string
	PublicAPIBaseURL   string

	// Redis（可选，用于缓存时配置；未启用则不连接）
	RedisEnabled  bool
	RedisAddr     string
	RedisPassword string
	RedisDB       int
	RedisEnv      string

	RabbitMQEnabled bool
	RabbitMQURL     string
	RabbitMQEnv     string

	WebhookMengyaSecret   string
	PaymentPendingTTLSecs int

	// GinDebug：为 true 时启用 Gin Debug（打印路由表等）；默认 false，日志更干净。
	GinDebug bool

	// EnableSwagger：为 true 时注册 /swagger UI；默认在 GIN_DEBUG 或 ENABLE_SWAGGER 为真时为 true。
	EnableSwagger bool
}

// 应用环境：在未设置 DATABASE_DSN / RABBITMQ_ENV 时决定默认值。
// APP_ENV=production → 生产库 DSN、RABBITMQ_ENV 默认 prod。
// 否则 → 开发默认（测试库、RabbitMQ 开发环境）。
const (
	EnvDevelopment = "development"
	EnvProduction  = "production"
)

// 内建 DSN：当 DATABASE_DSN 为空时使用。
const (
	TestDSN = "mengyastore-test:mengyastore-test@tcp(10.1.1.100:3306)/mengyastore-test?charset=utf8mb4&parseTime=True&loc=Local"
	ProdDSN = "mengyastore:mengyastore@tcp(192.168.1.100:3306)/mengyastore?charset=utf8mb4&parseTime=True&loc=Local"

	DefaultRabbitMQHost    = "10.1.1.233"
	DefaultRabbitMQPort    = "5672"
	DefaultRabbitVHost     = "mengyastore-dev"
	DefaultRabbitMQUser    = "admin"
	ProdRabbitMQHost       = "192.168.1.100"
	DefaultRabbitVHostProd = "mengyastore-prod"

	// Redis：与 MySQL 同网段；未设置 REDIS_ADDR / REDIS_PASSWORD 时按 APP_ENV 填入
	TestRedisAddr = "10.1.1.100:6379"
	ProdRedisAddr = "192.168.1.100:6379"
	// 内网默认口令（可用环境变量 REDIS_PASSWORD 覆盖）
	DefaultRedisPassword = "tyh@19900420"
)

// Load 读取可选的 env 文件，再从进程环境组装 Config。
//
// 解析 env 文件的顺序：
//  1. 环境变量 ENV_FILE 指定的文件（若设置了）
//  2. 当前工作目录下的 .env.development（不存在则忽略）
//
// 环境变量说明（除非注明否则均可选）：
//
//	APP_ENV               — development | production（默认 development）
//	ADMIN_TOKEN           — 管理端 API 令牌（默认 changeme）
//	AUTH_API_URL          — 萌芽认证中心 SproutGate 根 URL
//	DATABASE_DSN          — MySQL DSN；为空则按 APP_ENV 选用 TestDSN / ProdDSN
//	RABBITMQ_ENABLED      — true/false
//	RABBITMQ_URL          — 完整 amqp URL
//	RABBITMQ_ENV          — dev | prod（默认随 APP_ENV）
//	RABBITMQ_PASSWORD     — 若已启用 MQ 但未设 RABBITMQ_URL，则用默认主机/vhost 拼 URL 时需要口令
//
//	HTTP_LISTEN_ADDR      — 进程监听，默认 :8080
//	PUBLIC_API_BASE_URL   — 对外 API 基地址（反向代理场景）
//
//	WEBHOOK_MENGYA_SECRET — 若设置，到账 Webhook 须带相同请求头 X-Webhook-Secret
//	PAYMENT_PENDING_SECONDS — 萌芽支付待支付超时（秒，默认 60）
//
//	GIN_DEBUG             — 1/true/yes/on：Gin Debug；默认关闭；为真时同时开启 Swagger UI（/swagger）
//	ENABLE_SWAGGER        — 1/true/yes/on：启用 Swagger UI；与 GIN_DEBUG 任一为真即注册 /swagger
//	WEBHOOK_LOG_VERBOSE   — 1/true：萌芽 Webhook 日志附带 notice/body 摘要（排查渠道用）
//
//	REDIS_ENABLED         — 默认 true；显式 false/0/off 则关闭
//	REDIS_ADDR            — 默认 development→TestRedisAddr，production→ProdRedisAddr
//	REDIS_PASSWORD        — 默认 DefaultRedisPassword（建议生产用环境变量覆盖）
//	REDIS_DB              — 逻辑库编号，默认 1
//	REDIS_ENV             — dev|prod（展示用 Key 前缀环境）
func Load() (*Config, error) {
	loadDotenv()

	appEnv := normalizeAppEnv(os.Getenv("APP_ENV"))

	cfg := &Config{
		AppEnv:      appEnv,
		AdminToken:  strings.TrimSpace(os.Getenv("ADMIN_TOKEN")),
		AuthAPIURL:  strings.TrimSpace(os.Getenv("AUTH_API_URL")),
		DatabaseDSN: strings.TrimSpace(os.Getenv("DATABASE_DSN")),
		RabbitMQURL: strings.TrimSpace(os.Getenv("RABBITMQ_URL")),
	}

	if cfg.AdminToken == "" {
		cfg.AdminToken = "changeme"
	}

	if cfg.DatabaseDSN == "" {
		if appEnv == EnvProduction {
			cfg.DatabaseDSN = ProdDSN
		} else {
			cfg.DatabaseDSN = TestDSN
		}
	}

	if v := os.Getenv("RABBITMQ_ENABLED"); v != "" {
		cfg.RabbitMQEnabled = v == "true" || v == "1"
	}

	cfg.RabbitMQEnv = strings.TrimSpace(os.Getenv("RABBITMQ_ENV"))
	if cfg.RabbitMQEnv == "" {
		if appEnv == EnvProduction {
			cfg.RabbitMQEnv = "prod"
		} else {
			cfg.RabbitMQEnv = "dev"
		}
	}

	if cfg.RabbitMQURL == "" && cfg.RabbitMQEnabled {
		cfg.RabbitMQURL = composeRabbitMQURL(cfg)
	}

	if v := os.Getenv("HTTP_LISTEN_ADDR"); v != "" {
		cfg.HTTPListenAddr = strings.TrimSpace(v)
	}
	if cfg.HTTPListenAddr == "" {
		cfg.HTTPListenAddr = ":8080"
	}
	cfg.PublicAPIBaseURL = strings.TrimSpace(os.Getenv("PUBLIC_API_BASE_URL"))

	cfg.RedisEnabled = redisEnabledFromEnv(os.Getenv("REDIS_ENABLED"))
	cfg.RedisAddr = strings.TrimSpace(os.Getenv("REDIS_ADDR"))
	cfg.RedisPassword = os.Getenv("REDIS_PASSWORD")
	if v := os.Getenv("REDIS_DB"); v != "" {
		if n, err := strconv.Atoi(v); err == nil {
			cfg.RedisDB = n
		}
	}
	cfg.RedisEnv = strings.TrimSpace(os.Getenv("REDIS_ENV"))
	if cfg.RedisEnv == "" {
		if appEnv == EnvProduction {
			cfg.RedisEnv = "prod"
		} else {
			cfg.RedisEnv = "dev"
		}
	}

	if cfg.RedisEnabled {
		if cfg.RedisAddr == "" {
			if appEnv == EnvProduction {
				cfg.RedisAddr = ProdRedisAddr
			} else {
				cfg.RedisAddr = TestRedisAddr
			}
		}
		if cfg.RedisPassword == "" {
			cfg.RedisPassword = DefaultRedisPassword
		}
		if cfg.RedisDB == 0 {
			cfg.RedisDB = 1
		}
	}

	cfg.WebhookMengyaSecret = strings.TrimSpace(os.Getenv("WEBHOOK_MENGYA_SECRET"))
	if sec := strings.TrimSpace(os.Getenv("PAYMENT_PENDING_SECONDS")); sec != "" {
		if n, err := strconv.Atoi(sec); err == nil && n > 0 {
			cfg.PaymentPendingTTLSecs = n
		}
	}
	if cfg.PaymentPendingTTLSecs <= 0 {
		cfg.PaymentPendingTTLSecs = 60
	}

	cfg.GinDebug = envTruthy(os.Getenv("GIN_DEBUG"))

	cfg.EnableSwagger = cfg.GinDebug || envTruthy(os.Getenv("ENABLE_SWAGGER"))

	return cfg, nil
}

// envTruthy：将 1、true、yes、on 视为真（不区分大小写）。
func envTruthy(s string) bool {
	switch strings.ToLower(strings.TrimSpace(s)) {
	case "1", "true", "yes", "on":
		return true
	default:
		return false
	}
}

// redisEnabledFromEnv：除非显式关闭，否则默认启用 Redis。
func redisEnabledFromEnv(v string) bool {
	s := strings.ToLower(strings.TrimSpace(v))
	if s == "false" || s == "0" || s == "no" || s == "off" {
		return false
	}
	if s == "true" || s == "1" || s == "yes" || s == "on" {
		return true
	}
	return true
}

func loadDotenv() {
	if f := strings.TrimSpace(os.Getenv("ENV_FILE")); f != "" {
		_ = godotenv.Load(f)
		return
	}
	// 本地开发默认文件名；不存在则忽略。
	_ = godotenv.Load(filepath.Clean(".env.development"))
}

func normalizeAppEnv(s string) string {
	switch strings.ToLower(strings.TrimSpace(s)) {
	case "production", "prod":
		return EnvProduction
	default:
		return EnvDevelopment
	}
}

func composeRabbitMQURL(cfg *Config) string {
	pass := os.Getenv("RABBITMQ_PASSWORD")
	if pass == "" {
		return ""
	}
	host := os.Getenv("RABBITMQ_HOST")
	port := os.Getenv("RABBITMQ_PORT")
	user := os.Getenv("RABBITMQ_USER")
	vhost := os.Getenv("RABBITMQ_VHOST")
	if host == "" {
		if cfg.RabbitMQEnv == "prod" {
			host = ProdRabbitMQHost
		} else {
			host = DefaultRabbitMQHost
		}
	}
	if port == "" {
		port = DefaultRabbitMQPort
	}
	if user == "" {
		user = DefaultRabbitMQUser
	}
	if vhost == "" {
		if cfg.RabbitMQEnv == "prod" {
			vhost = DefaultRabbitVHostProd
		} else {
			vhost = DefaultRabbitVHost
		}
	}
	var path string
	if vhost == "/" {
		path = "/%2F"
	} else {
		path = "/" + url.PathEscape(vhost)
	}
	u := url.URL{
		Scheme: "amqp",
		User:   url.UserPassword(user, pass),
		Host:   host + ":" + port,
		Path:   path,
	}
	return u.String()
}
