package dbmigrate

import (
	"errors"
	"fmt"
	"log/slog"
	"os"
	"strings"

	"github.com/golang-migrate/migrate/v4"
	_ "github.com/golang-migrate/migrate/v4/database/postgres"
	"github.com/golang-migrate/migrate/v4/source/iofs"

	"github.com/ultisuite/ulti-backend/migrations"
)

// Up applies pending SQL migrations. No-op when ULTID_AUTO_MIGRATE=false.
func Up(databaseURL string) error {
	if !autoMigrateEnabled() {
		slog.Info("database auto-migrate disabled")
		return nil
	}
	if strings.TrimSpace(databaseURL) == "" {
		return fmt.Errorf("empty database URL")
	}

	source, err := iofs.New(migrations.Files, ".")
	if err != nil {
		return fmt.Errorf("migration source: %w", err)
	}

	m, err := migrate.NewWithSourceInstance("iofs", source, databaseURL)
	if err != nil {
		return fmt.Errorf("migrate init: %w", err)
	}
	defer func() {
		srcErr, dbErr := m.Close()
		if srcErr != nil {
			slog.Warn("migrate close source", "error", srcErr)
		}
		if dbErr != nil {
			slog.Warn("migrate close database", "error", dbErr)
		}
	}()

	if err := m.Up(); err != nil {
		if errors.Is(err, migrate.ErrNoChange) {
			slog.Info("database schema up to date")
			return nil
		}
		return fmt.Errorf("migrate up: %w", err)
	}

	slog.Info("database migrations applied")
	return nil
}

func autoMigrateEnabled() bool {
	v := strings.ToLower(strings.TrimSpace(os.Getenv("ULTID_AUTO_MIGRATE")))
	if v == "false" || v == "0" || v == "no" {
		return false
	}
	return true
}
