package config

import (
	"errors"
	"fmt"
	"strings"
	"sync/atomic"
	"time"

	"github.com/break/junhong_cmp_fiber/pkg/constants"
)

// globalConfig 保存当前配置，支持原子访问
var globalConfig atomic.Pointer[Config]

// Config 应用配置
type Config struct {
	Server             ServerConfig             `mapstructure:"server"`
	Redis              RedisConfig              `mapstructure:"redis"`
	Database           DatabaseConfig           `mapstructure:"database"`
	Queue              QueueConfig              `mapstructure:"queue"`
	Logging            LoggingConfig            `mapstructure:"logging"`
	Middleware         MiddlewareConfig         `mapstructure:"middleware"`
	Client             ClientConfig             `mapstructure:"client"`
	SMS                SMSConfig                `mapstructure:"sms"`
	JWT                JWTConfig                `mapstructure:"jwt"`
	DefaultAdmin       DefaultAdminConfig       `mapstructure:"default_admin"`
	Storage            StorageConfig            `mapstructure:"storage"`
	Gateway            GatewayConfig            `mapstructure:"gateway"`
	PollingAutoTrigger PollingAutoTriggerConfig `mapstructure:"polling_auto_trigger"`
	Polling            PollingConfig            `mapstructure:"polling"`
	Worker             WorkerConfig             `mapstructure:"worker"`
	WeCom              WeComConfig              `mapstructure:"wecom"`
	Approval           ApprovalConfig           `mapstructure:"approval"`
}

// ServerConfig HTTP 服务器配置
type ServerConfig struct {
	Address         string        `mapstructure:"address"`          // 例如 ":3000"
	ReadTimeout     time.Duration `mapstructure:"read_timeout"`     // 例如 "10s"
	WriteTimeout    time.Duration `mapstructure:"write_timeout"`    // 例如 "10s"
	ShutdownTimeout time.Duration `mapstructure:"shutdown_timeout"` // 例如 "30s"
	Prefork         bool          `mapstructure:"prefork"`          // 多进程模式
}

// RedisConfig Redis 连接配置
type RedisConfig struct {
	Address      string        `mapstructure:"address"`        // 例如 "localhost"
	Port         int           `mapstructure:"port"`           // 例如 "6379"
	Password     string        `mapstructure:"password"`       // 无认证时留空
	DB           int           `mapstructure:"db"`             // 数据库编号（0-15）
	PoolSize     int           `mapstructure:"pool_size"`      // 最大连接数
	MinIdleConns int           `mapstructure:"min_idle_conns"` // 保活连接数
	DialTimeout  time.Duration `mapstructure:"dial_timeout"`   // 例如 "5s"
	ReadTimeout  time.Duration `mapstructure:"read_timeout"`   // 例如 "3s"
	WriteTimeout time.Duration `mapstructure:"write_timeout"`  // 例如 "3s"
}

// DatabaseConfig 数据库连接配置
type DatabaseConfig struct {
	Host            string        `mapstructure:"host"`              // 数据库主机地址
	Port            int           `mapstructure:"port"`              // 数据库端口
	User            string        `mapstructure:"user"`              // 数据库用户名
	Password        string        `mapstructure:"password"`          // 数据库密码（明文存储）
	DBName          string        `mapstructure:"dbname"`            // 数据库名称
	SSLMode         string        `mapstructure:"sslmode"`           // SSL 模式：disable, require, verify-ca, verify-full
	MaxOpenConns    int           `mapstructure:"max_open_conns"`    // 最大打开连接数（默认：25）
	MaxIdleConns    int           `mapstructure:"max_idle_conns"`    // 最大空闲连接数（默认：10）
	ConnMaxLifetime time.Duration `mapstructure:"conn_max_lifetime"` // 连接最大生命周期（默认：5m）
}

// QueueConfig 任务队列配置
type QueueConfig struct {
	Concurrency int            `mapstructure:"concurrency"` // Worker 并发数（默认：10）
	Queues      map[string]int `mapstructure:"queues"`      // Asynq 队列取任务权重（不是业务并发上限）
	RetryMax    int            `mapstructure:"retry_max"`   // 最大重试次数（默认：5）
	Timeout     time.Duration  `mapstructure:"timeout"`     // 任务超时时间（默认：10m）
}

// LoggingConfig 日志配置
type LoggingConfig struct {
	Level       string            `mapstructure:"level"`       // debug, info, warn, error
	Development bool              `mapstructure:"development"` // 启用开发模式（美化输出）
	AppLog      LogRotationConfig `mapstructure:"app_log"`     // 应用日志配置
	AccessLog   LogRotationConfig `mapstructure:"access_log"`  // HTTP 访问日志配置
}

// LogRotationConfig Lumberjack 日志轮转配置
type LogRotationConfig struct {
	Filename   string `mapstructure:"filename"`    // 日志文件路径
	MaxSize    int    `mapstructure:"max_size"`    // 轮转前的最大大小（MB）
	MaxBackups int    `mapstructure:"max_backups"` // 保留的旧文件最大数量
	MaxAge     int    `mapstructure:"max_age"`     // 保留旧文件的最大天数
	Compress   bool   `mapstructure:"compress"`    // 压缩轮转的文件
}

// MiddlewareConfig 中间件配置
type MiddlewareConfig struct {
	EnableRateLimiter bool              `mapstructure:"enable_rate_limiter"` // 启用限流器（默认：false）
	RateLimiter       RateLimiterConfig `mapstructure:"rate_limiter"`        // 限流器配置
	CORS              CORSConfig        `mapstructure:"cors"`                // 跨域配置
}

// ClientConfig 客户端行为开关配置
type ClientConfig struct {
	RequirePhoneBinding bool `mapstructure:"require_phone_binding"` // 是否要求个人客户绑定手机号
}

// RateLimiterConfig 限流器配置
type RateLimiterConfig struct {
	Max        int           `mapstructure:"max"`        // 时间窗口内的最大请求数
	Expiration time.Duration `mapstructure:"expiration"` // 时间窗口（例如 "1m"）
	Storage    string        `mapstructure:"storage"`    // "memory" 或 "redis"
}

// CORSConfig 跨域资源共享配置
type CORSConfig struct {
	Enabled          bool   `mapstructure:"enabled"`           // 是否启用 CORS
	AllowOrigins     string `mapstructure:"allow_origins"`     // 允许的来源，多个来源用逗号分隔
	AllowMethods     string `mapstructure:"allow_methods"`     // 允许的 HTTP 方法，多个方法用逗号分隔
	AllowHeaders     string `mapstructure:"allow_headers"`     // 允许的请求头，多个请求头用逗号分隔
	ExposeHeaders    string `mapstructure:"expose_headers"`    // 暴露给浏览器读取的响应头，多个响应头用逗号分隔
	AllowCredentials bool   `mapstructure:"allow_credentials"` // 是否允许携带凭证
	MaxAge           int    `mapstructure:"max_age"`           // 预检结果缓存秒数
}

// SMSConfig 短信服务配置
type SMSConfig struct {
	GatewayURL string        `mapstructure:"gateway_url"` // 短信网关地址
	Username   string        `mapstructure:"username"`    // 账号用户名
	Password   string        `mapstructure:"password"`    // 账号密码
	Signature  string        `mapstructure:"signature"`   // 短信签名（例如：【签名】）
	Timeout    time.Duration `mapstructure:"timeout"`     // 请求超时时间
}

// JWTConfig JWT 认证配置
type JWTConfig struct {
	SecretKey       string        `mapstructure:"secret_key"`        // JWT 签名密钥
	TokenDuration   time.Duration `mapstructure:"token_duration"`    // Token 有效期（C 端 JWT）
	AccessTokenTTL  time.Duration `mapstructure:"access_token_ttl"`  // 访问令牌有效期（B 端 Redis Token）
	RefreshTokenTTL time.Duration `mapstructure:"refresh_token_ttl"` // 刷新令牌有效期（B 端 Redis Token）
}

// DefaultAdminConfig 默认超级管理员配置
type DefaultAdminConfig struct {
	Username string `mapstructure:"username"`
	Password string `mapstructure:"password"`
	Phone    string `mapstructure:"phone"`
}

// StorageConfig 对象存储配置
type StorageConfig struct {
	Provider string        `mapstructure:"provider"` // 存储提供商：s3
	S3       S3Config      `mapstructure:"s3"`       // S3 兼容存储配置
	Presign  PresignConfig `mapstructure:"presign"`  // 预签名 URL 配置
	TempDir  string        `mapstructure:"temp_dir"` // 临时文件目录
}

// GatewayConfig Gateway 服务配置
type GatewayConfig struct {
	BaseURL   string `mapstructure:"base_url"`   // Gateway API 基础 URL
	AppID     string `mapstructure:"app_id"`     // 应用 ID
	AppSecret string `mapstructure:"app_secret"` // 应用密钥
	Timeout   int    `mapstructure:"timeout"`    // 超时时间（秒）
}

// WorkerConfig Worker 进程运行配置
type WorkerConfig struct {
	Role         string `mapstructure:"role"`          // Worker 运行角色：all、leader、consumer
	InstanceName string `mapstructure:"instance_name"` // Worker 实例名称，用于多实例日志区分
}

// ApprovalConfig 审批新旧入口切换配置。
type ApprovalConfig struct {
	LegacyRefundManualEnabled       bool `mapstructure:"legacy_refund_manual_enabled"`        // 是否保留退款人工通过与拒绝入口
	LegacyOfflineRechargePayEnabled bool `mapstructure:"legacy_offline_recharge_pay_enabled"` // 是否保留线下充值人工确认入口
}

// WeComConfig 企业微信 Adapter 运行配置。
type WeComConfig struct {
	BaseURL                 string        `mapstructure:"base_url"`                  // 企业微信 API 基础地址
	Timeout                 time.Duration `mapstructure:"timeout"`                   // 外部请求超时时间
	CredentialEncryptionKey string        `mapstructure:"credential_encryption_key"` // 数据库凭证 AES-256-GCM 加密密钥（Base64）
}

// PollingConfig 轮询通用配置
type PollingConfig struct {
	// VerboseLog 开启后，所有轮询 handler 在成功获取上游数据时以 Info 级别输出详细日志
	// 环境变量：JUNHONG_POLLING_VERBOSE_LOG
	VerboseLog bool `mapstructure:"verbose_log"`
}

// PollingAutoTriggerConfig 轮询自动触发配置
type PollingAutoTriggerConfig struct {
	// EnableAutoTrigger 是否启用C端实名自动触发
	// 环境变量：JUNHONG_POLLING_AUTO_TRIGGER_ENABLE_AUTO_TRIGGER
	EnableAutoTrigger bool `mapstructure:"enable_auto_trigger"`
	// AutoTriggerSystemUserID 自动触发使用的系统用户ID（暂用 SuperAdmin ID=1）
	// 环境变量：JUNHONG_POLLING_AUTO_TRIGGER_AUTO_TRIGGER_SYSTEM_USER_ID
	AutoTriggerSystemUserID int `mapstructure:"auto_trigger_system_user_id"`
}

// S3Config S3 兼容存储配置
type S3Config struct {
	Endpoint        string `mapstructure:"endpoint"`          // 服务端点（如：http://obs-helf.cucloud.cn）
	Region          string `mapstructure:"region"`            // 区域（如：cn-langfang-2）
	Bucket          string `mapstructure:"bucket"`            // 存储桶名称
	AccessKeyID     string `mapstructure:"access_key_id"`     // 访问密钥 ID
	SecretAccessKey string `mapstructure:"secret_access_key"` // 访问密钥
	UseSSL          bool   `mapstructure:"use_ssl"`           // 是否使用 SSL
	PathStyle       bool   `mapstructure:"path_style"`        // 是否使用路径风格（兼容性）
}

// PresignConfig 预签名 URL 配置
type PresignConfig struct {
	UploadExpires   time.Duration `mapstructure:"upload_expires"`   // 上传 URL 有效期（默认：15m）
	DownloadExpires time.Duration `mapstructure:"download_expires"` // 下载 URL 有效期（默认：24h）
}

type requiredField struct {
	value   string
	name    string
	envName string
}

func (c *Config) ValidateRequired() error {
	fields := []requiredField{
		{c.Database.Host, "database.host", "JUNHONG_DATABASE_HOST"},
		{c.Database.User, "database.user", "JUNHONG_DATABASE_USER"},
		{c.Database.Password, "database.password", "JUNHONG_DATABASE_PASSWORD"},
		{c.Database.DBName, "database.dbname", "JUNHONG_DATABASE_DBNAME"},
		{c.Redis.Address, "redis.address", "JUNHONG_REDIS_ADDRESS"},
		{c.JWT.SecretKey, "jwt.secret_key", "JUNHONG_JWT_SECRET_KEY"},
	}

	var missing []string
	for _, f := range fields {
		if f.value == "" {
			missing = append(missing, fmt.Sprintf("  - %s (环境变量: %s)", f.name, f.envName))
		}
	}

	if len(missing) > 0 {
		return fmt.Errorf("缺少必填配置项:\n%s", strings.Join(missing, "\n"))
	}

	return nil
}

func (c *Config) Validate() error {
	// 服务器验证
	if c.Server.Address == "" {
		return fmt.Errorf("invalid configuration: server.address: must be non-empty (current value: empty)")
	}
	if c.Server.ReadTimeout < 5*time.Second || c.Server.ReadTimeout > 300*time.Second {
		return fmt.Errorf("invalid configuration: server.read_timeout: duration out of range (current value: %s, expected: 5s-300s)", c.Server.ReadTimeout)
	}
	if c.Server.WriteTimeout < 5*time.Second || c.Server.WriteTimeout > 300*time.Second {
		return fmt.Errorf("invalid configuration: server.write_timeout: duration out of range (current value: %s, expected: 5s-300s)", c.Server.WriteTimeout)
	}
	if c.Server.ShutdownTimeout < 10*time.Second || c.Server.ShutdownTimeout > 120*time.Second {
		return fmt.Errorf("invalid configuration: server.shutdown_timeout: duration out of range (current value: %s, expected: 10s-120s)", c.Server.ShutdownTimeout)
	}

	// Redis 验证
	if c.Redis.Address == "" {
		return fmt.Errorf("invalid configuration: redis.address: must be non-empty (current value: empty)")
	}
	// Port 验证（独立字段）
	if c.Redis.Port <= 0 || c.Redis.Port > 65535 {
		return fmt.Errorf("invalid configuration: redis.port: port number out of range (current value: %d, expected: 1-65535)", c.Redis.Port)
	}
	if c.Redis.DB < 0 || c.Redis.DB > 15 {
		return fmt.Errorf("invalid configuration: redis.db: database number out of range (current value: %d, expected: 0-15)", c.Redis.DB)
	}
	if c.Redis.PoolSize <= 0 || c.Redis.PoolSize > 1000 {
		return fmt.Errorf("invalid configuration: redis.pool_size: pool size out of range (current value: %d, expected: 1-1000)", c.Redis.PoolSize)
	}
	if c.Redis.MinIdleConns < 0 || c.Redis.MinIdleConns > c.Redis.PoolSize {
		return fmt.Errorf("invalid configuration: redis.min_idle_conns: must be 0 to pool_size (current value: %d, pool_size: %d)", c.Redis.MinIdleConns, c.Redis.PoolSize)
	}

	// 日志验证
	validLevels := map[string]bool{"debug": true, "info": true, "warn": true, "error": true}
	if !validLevels[c.Logging.Level] {
		return fmt.Errorf("invalid configuration: logging.level: invalid log level (current value: %s, expected: debug, info, warn, error)", c.Logging.Level)
	}
	if c.Logging.AppLog.Filename == "" {
		return fmt.Errorf("invalid configuration: logging.app_log.filename: must be non-empty valid file path")
	}
	if c.Logging.AccessLog.Filename == "" {
		return fmt.Errorf("invalid configuration: logging.access_log.filename: must be non-empty valid file path")
	}
	if c.Logging.AppLog.MaxSize < 1 || c.Logging.AppLog.MaxSize > 1000 {
		return fmt.Errorf("invalid configuration: logging.app_log.max_size: size out of range (current value: %d, expected: 1-1000 MB)", c.Logging.AppLog.MaxSize)
	}
	if c.Logging.AccessLog.MaxSize < 1 || c.Logging.AccessLog.MaxSize > 1000 {
		return fmt.Errorf("invalid configuration: logging.access_log.max_size: size out of range (current value: %d, expected: 1-1000 MB)", c.Logging.AccessLog.MaxSize)
	}

	// 中间件验证
	if c.Middleware.RateLimiter.Max <= 0 {
		c.Middleware.RateLimiter.Max = 100 // 默认值
	}
	if c.Middleware.RateLimiter.Max > 10000 {
		return fmt.Errorf("invalid configuration: middleware.rate_limiter.max: request limit out of range (current value: %d, expected: 1-10000)", c.Middleware.RateLimiter.Max)
	}
	validStorage := map[string]bool{"memory": true, "redis": true}
	if c.Middleware.RateLimiter.Storage != "" && !validStorage[c.Middleware.RateLimiter.Storage] {
		return fmt.Errorf("invalid configuration: middleware.rate_limiter.storage: invalid storage type (current value: %s, expected: memory or redis)", c.Middleware.RateLimiter.Storage)
	}
	if c.Middleware.CORS.Enabled {
		if strings.TrimSpace(c.Middleware.CORS.AllowOrigins) == "" {
			return fmt.Errorf("invalid configuration: middleware.cors.allow_origins: must be non-empty when CORS is enabled")
		}
		if c.Middleware.CORS.AllowCredentials && strings.TrimSpace(c.Middleware.CORS.AllowOrigins) == "*" {
			return fmt.Errorf("invalid configuration: middleware.cors.allow_origins: wildcard origin is not allowed when allow_credentials is true")
		}
		if strings.TrimSpace(c.Middleware.CORS.AllowMethods) == "" {
			return fmt.Errorf("invalid configuration: middleware.cors.allow_methods: must be non-empty when CORS is enabled")
		}
		if c.Middleware.CORS.MaxAge < 0 {
			return fmt.Errorf("invalid configuration: middleware.cors.max_age: must be greater than or equal to 0")
		}
	}

	// 短信服务验证（可选，配置 GatewayURL 时才验证其他字段）
	if c.SMS.GatewayURL != "" {
		if c.SMS.Username == "" {
			return fmt.Errorf("invalid configuration: sms.username: must be non-empty when gateway_url is configured")
		}
		if c.SMS.Password == "" {
			return fmt.Errorf("invalid configuration: sms.password: must be non-empty when gateway_url is configured")
		}
		if c.SMS.Signature == "" {
			return fmt.Errorf("invalid configuration: sms.signature: must be non-empty when gateway_url is configured")
		}
		if c.SMS.Timeout > 0 && (c.SMS.Timeout < 5*time.Second || c.SMS.Timeout > 60*time.Second) {
			return fmt.Errorf("invalid configuration: sms.timeout: duration out of range (current value: %s, expected: 5s-60s)", c.SMS.Timeout)
		}
	}

	// JWT 验证（SecretKey 必填验证在 ValidateRequired 中处理）
	if len(c.JWT.SecretKey) > 0 && len(c.JWT.SecretKey) < 32 {
		return fmt.Errorf("invalid configuration: jwt.secret_key: secret key too short (current length: %d, expected: >= 32)", len(c.JWT.SecretKey))
	}
	if c.JWT.TokenDuration < 1*time.Hour || c.JWT.TokenDuration > 720*time.Hour {
		return fmt.Errorf("invalid configuration: jwt.token_duration: duration out of range (current value: %s, expected: 1h-720h)", c.JWT.TokenDuration)
	}
	if c.JWT.AccessTokenTTL < 1*time.Hour || c.JWT.AccessTokenTTL > 168*time.Hour {
		return fmt.Errorf("invalid configuration: jwt.access_token_ttl: duration out of range (current value: %s, expected: 1h-168h)", c.JWT.AccessTokenTTL)
	}
	if c.JWT.RefreshTokenTTL < 24*time.Hour || c.JWT.RefreshTokenTTL > 720*time.Hour {
		return fmt.Errorf("invalid configuration: jwt.refresh_token_ttl: duration out of range (current value: %s, expected: 24h-720h)", c.JWT.RefreshTokenTTL)
	}

	// Gateway 验证（可选，配置 BaseURL 时才验证其他字段）
	if c.Gateway.BaseURL != "" {
		if !strings.HasPrefix(c.Gateway.BaseURL, "http://") && !strings.HasPrefix(c.Gateway.BaseURL, "https://") {
			return fmt.Errorf("invalid configuration: gateway.base_url: must start with http:// or https:// (current value: %s)", c.Gateway.BaseURL)
		}
		if c.Gateway.AppID == "" {
			return fmt.Errorf("invalid configuration: gateway.app_id: must be non-empty when base_url is configured")
		}
		if c.Gateway.AppSecret == "" {
			return fmt.Errorf("invalid configuration: gateway.app_secret: must be non-empty when base_url is configured")
		}
		if c.Gateway.Timeout < 5 || c.Gateway.Timeout > 300 {
			return fmt.Errorf("invalid configuration: gateway.timeout: timeout out of range (current value: %d, expected: 5-300 seconds)", c.Gateway.Timeout)
		}
	}

	validWorkerRoles := map[string]bool{
		constants.WorkerRoleAll:      true,
		constants.WorkerRoleLeader:   true,
		constants.WorkerRoleConsumer: true,
	}
	if !validWorkerRoles[c.Worker.Role] {
		return fmt.Errorf(
			"invalid configuration: worker.role: invalid worker role (current value: %s, expected: %s, %s, %s)",
			c.Worker.Role,
			constants.WorkerRoleAll,
			constants.WorkerRoleLeader,
			constants.WorkerRoleConsumer,
		)
	}

	return nil
}

// Get 返回当前配置
func Get() *Config {
	return globalConfig.Load()
}

// Set 原子地更新全局配置
func Set(cfg *Config) error {
	if cfg == nil {
		return errors.New("config cannot be nil")
	}
	if err := cfg.Validate(); err != nil {
		return err
	}
	globalConfig.Store(cfg)
	return nil
}
