package database

import (
	"fmt"
	"log"
	"os"
	"strings"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

// loadDotEnv 在当前工作目录查找 .env 文件并加载到进程环境变量中（已存在的变量不覆盖）。
// 仅用于本地开发场景：生产部署通过 docker-compose / 容器环境变量直接注入，没有 .env 文件时静默跳过。
func loadDotEnv() {
	data, err := os.ReadFile(".env")
	if err != nil {
		return
	}
	for _, line := range strings.Split(string(data), "\n") {
		line = strings.TrimSpace(line)
		if line == "" || strings.HasPrefix(line, "#") {
			continue
		}
		key, value, ok := strings.Cut(line, "=")
		if !ok {
			continue
		}
		key = strings.TrimSpace(key)
		if key == "" {
			continue
		}
		if _, exists := os.LookupEnv(key); exists {
			continue
		}
		os.Setenv(key, strings.TrimSpace(value))
	}
}

// DBConfig holds MySQL connection parameters.
type DBConfig struct {
	Host     string
	Port     string
	User     string
	Password string
	DBName   string
}

func (c DBConfig) DSN() string {
	return fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
		c.User, c.Password, c.Host, c.Port, c.DBName)
}

// envConfig 从环境变量读取连接参数。Host/User/Password 没有内置默认值，必须由
// 部署环境（本地 shell、.env、docker-compose 等）显式提供；DBName 默认统一为
// "sproutgate"，开发和生产环境共用同一个库名。
func envConfig() (DBConfig, error) {
	host := os.Getenv("DB_HOST")
	user := os.Getenv("DB_USER")
	password := os.Getenv("DB_PASSWORD")
	if host == "" || user == "" || password == "" {
		return DBConfig{}, fmt.Errorf("缺少数据库环境变量，请设置 DB_HOST/DB_USER/DB_PASSWORD（或直接设置 DB_DSN）")
	}

	port := os.Getenv("DB_PORT")
	if port == "" {
		port = "3306"
	}
	dbName := os.Getenv("DB_NAME")
	if dbName == "" {
		dbName = "sproutgate"
	}

	return DBConfig{Host: host, Port: port, User: user, Password: password, DBName: dbName}, nil
}

// Open 根据环境变量打开数据库连接。
// 优先级：DB_DSN（完整自定义连接串）> DB_HOST/DB_PORT/DB_USER/DB_PASSWORD/DB_NAME
func Open() (*gorm.DB, error) {
	loadDotEnv()

	dsn := os.Getenv("DB_DSN")
	if dsn == "" {
		cfg, err := envConfig()
		if err != nil {
			return nil, err
		}
		dsn = cfg.DSN()
		log.Printf("[database] 使用数据库 %s:%s/%s", cfg.Host, cfg.Port, cfg.DBName)
	} else {
		log.Println("[database] 使用自定义 DB_DSN")
	}

	logLevel := logger.Info
	if os.Getenv("GIN_MODE") == "release" {
		logLevel = logger.Warn
	}

	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: logger.Default.LogMode(logLevel),
	})
	if err != nil {
		return nil, fmt.Errorf("连接数据库失败: %w", err)
	}

	sqlDB, err := db.DB()
	if err != nil {
		return nil, err
	}
	sqlDB.SetMaxOpenConns(25)
	sqlDB.SetMaxIdleConns(5)

	return db, nil
}
