package config

import (
	"bufio"
	"log"
	"os"
	"strings"

	"github.com/spf13/viper"
)

// Config 应用总配置
type Config struct {
	Server   ServerConfig   `mapstructure:"server"`
	Database DatabaseConfig `mapstructure:"database"`
	Session  SessionConfig  `mapstructure:"session"`
	Bcrypt   BcryptConfig   `mapstructure:"bcrypt"`
	Roles    RolesConfig    `mapstructure:"roles"`
	Audit    AuditConfig    `mapstructure:"audit"`
}

// AuditConfig 审核系统配置（config.yaml 提供默认值，站点设置可运行时覆盖）
type AuditConfig struct {
	Enabled        bool `mapstructure:"enabled"`
	UsernameAudit  bool `mapstructure:"username_audit"`
	AvatarAudit    bool `mapstructure:"avatar_audit"`
	BioAudit       bool `mapstructure:"bio_audit"`
}

type ServerConfig struct {
	Port string `mapstructure:"port"`
	Mode string `mapstructure:"mode"`
}

type DatabaseConfig struct {
	Host     string `mapstructure:"host"`
	Port     string `mapstructure:"port"`
	User     string `mapstructure:"user"`
	Password string `mapstructure:"password"`
	DBName   string `mapstructure:"dbname"`
	SSLMode  string `mapstructure:"sslmode"`
}

// SessionConfig 服务端会话配置
type SessionConfig struct {
	IdleTimeout     int `mapstructure:"idle_timeout"`     // 不记住我：空闲超时（分钟），默认 1440（24小时）
	RememberTimeout int `mapstructure:"remember_timeout"` // 记住我：空闲超时（分钟），默认 43200（30天）
	CleanupInterval int `mapstructure:"cleanup_interval"` // 后台清理间隔（秒），默认 300
}

type BcryptConfig struct {
	Cost int `mapstructure:"cost"`
}

// RolesConfig 角色配置（可扩展，新增角色只需改 config.yaml）
type RolesConfig struct {
	Levels      map[string]int      `mapstructure:"levels"`
	Names       map[string]string   `mapstructure:"names"`
	Permissions RolesPermissions    `mapstructure:"permissions"`
}

// RolesPermissions 角色间操作权限
type RolesPermissions struct {
	OperableRoles map[string][]string `mapstructure:"operable_roles"`
}

// 全局配置实例（初始化后只读）
var App *Config

// Load 加载配置：config.yaml → .env 覆盖
func Load(configPath string) *Config {
	// 1. 从 .env 加载环境变量（优先于 config.yaml）
	loadEnvFile(".env")

	v := viper.New()

	// 2. 读取 config.yaml
	v.SetConfigFile(configPath)
	v.SetConfigType("yaml")
	if err := v.ReadInConfig(); err != nil {
		log.Fatalf("读取配置文件失败: %v", err)
	}

	// 3. 环境变量覆盖（DATABASE_PASSWORD → database.password）
	v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
	v.AutomaticEnv()
	bindEnvOverride(v)

	c := &Config{}
	if err := v.Unmarshal(c); err != nil {
		log.Fatalf("解析配置失败: %v", err)
	}

	log.Printf("[Config] Session.IdleTimeout=%d min Session.RememberTimeout=%d min Session.CleanupInterval=%d s | Server.Mode=%s",
		c.Session.IdleTimeout, c.Session.RememberTimeout, c.Session.CleanupInterval, c.Server.Mode)

	App = c
	return c
}

// loadEnvFile 读取 .env 文件并设置环境变量（仅当环境变量未设置时）
func loadEnvFile(path string) {
	f, err := os.Open(path)
	if err != nil {
		return // .env 不存在，跳过
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		if line == "" || strings.HasPrefix(line, "#") {
			continue
		}
		parts := strings.SplitN(line, "=", 2)
		if len(parts) != 2 {
			continue
		}
		key := strings.TrimSpace(parts[0])
		val := strings.TrimSpace(parts[1])
		if os.Getenv(key) == "" {
			os.Setenv(key, val)
		}
	}
}

// bindEnvOverride 将环境变量映射到 config 的嵌套键
func bindEnvOverride(v *viper.Viper) {
	_ = v.BindEnv("database.password", "DATABASE_PASSWORD")
}

// DSN 返回 PostgreSQL 连接字符串
func (d DatabaseConfig) DSN() string {
	return "host=" + d.Host +
		" port=" + d.Port +
		" user=" + d.User +
		" password=" + d.Password +
		" dbname=" + d.DBName +
		" sslmode=" + d.SSLMode
}
