package config

import (
	"fmt"
	"os"
	"time"

	"github.com/spf13/viper"
)

type Config struct {
	App       AppConfig       `mapstructure:"app"`
	Server    ServerConfig    `mapstructure:"server"`
	Security  SecurityConfig  `mapstructure:"security"`
	SMS       SMSConfig       `mapstructure:"sms"`
	Database  DatabaseConfig  `mapstructure:"database"`
	Timezone  string          `mapstructure:"timezone"`
	APITokens []APIToken      `mapstructure:"api_tokens"`
}

type AppConfig struct {
	Name    string `mapstructure:"name"`
	Version string `mapstructure:"version"`
}

type ServerConfig struct {
	Host  string `mapstructure:"host"`
	Port  int    `mapstructure:"port"`
	Debug bool   `mapstructure:"debug"`
}

type SecurityConfig struct {
	Enabled          bool   `mapstructure:"enabled"`
	Username         string `mapstructure:"username"`
	Password         string `mapstructure:"password"`
	SessionLifetime  int    `mapstructure:"session_lifetime"`
	SecretKey        string `mapstructure:"secret_key"`
	SignVerify       bool   `mapstructure:"sign_verify"`
	SignMaxAge       int64  `mapstructure:"sign_max_age"`
}

type SMSConfig struct {
	MaxMessages  int  `mapstructure:"max_messages"`
	AutoCleanup  bool `mapstructure:"auto_cleanup"`
	CleanupDays  int  `mapstructure:"cleanup_days"`
}

type DatabaseConfig struct {
	Path string `mapstructure:"path"`
}

type APIToken struct {
	Name    string `mapstructure:"name"`
	Token   string `mapstructure:"token"`
	Secret  string `mapstructure:"secret"`
	Enabled bool   `mapstructure:"enabled"`
}

var cfg *Config

func Load(configPath string) (*Config, error) {
	viper.SetConfigFile(configPath)
	viper.SetConfigType("yaml")

	// 允许环境变量覆盖
	viper.AutomaticEnv()

	if err := viper.ReadInConfig(); err != nil {
		return nil, fmt.Errorf("读取配置文件失败: %w", err)
	}

	cfg = &Config{}
	if err := viper.Unmarshal(cfg); err != nil {
		return nil, fmt.Errorf("解析配置文件失败: %w", err)
	}

	return cfg, nil
}

func Get() *Config {
	return cfg
}

// GetSessionLifetimeDuration 返回会话 lifetime 为 duration
func (c *Config) GetSessionLifetimeDuration() time.Duration {
	return time.Duration(c.Security.SessionLifetime) * time.Second
}

// GetSignMaxAgeDuration 返回签名最大有效期
func (c *Config) GetSignMaxAgeDuration() time.Duration {
	return time.Duration(c.Security.SignMaxAge) * time.Millisecond
}

// GetServerAddress 返回服务器地址
func (c *Config) GetServerAddress() string {
	return fmt.Sprintf("%s:%d", c.Server.Host, c.Server.Port)
}

// GetTokenByName 根据名称获取 Token 配置
func (c *Config) GetTokenByName(name string) *APIToken {
	for i := range c.APITokens {
		if c.APITokens[i].Name == name && c.APITokens[i].Enabled {
			return &c.APITokens[i]
		}
	}
	return nil
}

// GetTokenByValue 根据 token 值获取配置
func (c *Config) GetTokenByValue(token string) *APIToken {
	for i := range c.APITokens {
		if c.APITokens[i].Token == token && c.APITokens[i].Enabled {
			return &c.APITokens[i]
		}
	}
	return nil
}

// Save 保存配置到文件
func (c *Config) Save(path string) error {
	viper.Set("app", c.App)
	viper.Set("server", c.Server)
	viper.Set("security", c.Security)
	viper.Set("sms", c.SMS)
	viper.Set("database", c.Database)
	viper.Set("timezone", c.Timezone)
	viper.Set("api_tokens", c.APITokens)

	return viper.WriteConfigAs(path)
}

// LoadDefault 加载默认配置文件
func LoadDefault() (*Config, error) {
	configPath := "config.yaml"
	if _, err := os.Stat(configPath); os.IsNotExist(err) {
		// 尝试查找上层目录
		if _, err := os.Stat("../config.yaml"); err == nil {
			configPath = "../config.yaml"
		}
	}
	return Load(configPath)
}
