package db

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"server/internal/models"

	"gorm.io/driver/postgres"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

type Config struct {
	Driver string
	DSN    string
}

// Init opens the configured database connection and runs schema migrations.
func Init(cfg Config) (*gorm.DB, error) {
	switch cfg.Driver {
	case "sqlite":
		if err := ensureSQLiteDir(cfg.DSN); err != nil {
			return nil, fmt.Errorf("prepare sqlite path: %w", err)
		}
		db, err := gorm.Open(sqlite.Open(cfg.DSN), &gorm.Config{})
		if err != nil {
			return nil, fmt.Errorf("open sqlite: %w", err)
		}
		if err := db.AutoMigrate(&models.User{}, &models.UserDetails{}, &models.UserPreferences{}, &models.Session{}, &models.PasswordResetToken{}); err != nil {
			return nil, fmt.Errorf("migrate user: %w", err)
		}
		return db, nil
	case "postgres":
		db, err := gorm.Open(postgres.Open(cfg.DSN), &gorm.Config{})
		if err != nil {
			return nil, fmt.Errorf("open postgres: %w", err)
		}
		if err := db.AutoMigrate(&models.User{}, &models.UserDetails{}, &models.UserPreferences{}, &models.Session{}, &models.PasswordResetToken{}); err != nil {
			return nil, fmt.Errorf("migrate user: %w", err)
		}
		return db, nil
	default:
		return nil, fmt.Errorf("unsupported driver %q", cfg.Driver)
	}
}

func ensureSQLiteDir(dsn string) error {
	pathSpec := dsn
	if idx := strings.Index(pathSpec, "?"); idx >= 0 {
		pathSpec = pathSpec[:idx]
	}
	pathSpec = strings.TrimPrefix(pathSpec, "file:")
	if pathSpec == "" || strings.Contains(pathSpec, ":memory:") {
		return nil
	}
	dir := filepath.Dir(pathSpec)
	if dir == "." || dir == "" {
		return nil
	}
	return os.MkdirAll(dir, 0o755)
}
