package database_test

import (
	"os"
	"regexp"
	"testing"

	"github.com/DATA-DOG/go-sqlmock"
	"github.com/rede5/gohorsejobs/backend/internal/database"
)

func TestBuildConnectionString(t *testing.T) {
	// Backup env vars
	oldURL := os.Getenv("DATABASE_URL")
	oldHost := os.Getenv("DB_HOST")
	oldUser := os.Getenv("DB_USER")
	oldPass := os.Getenv("DB_PASSWORD")
	oldName := os.Getenv("DB_NAME")
	oldPort := os.Getenv("DB_PORT")
	oldSSL := os.Getenv("DB_SSLMODE")

	defer func() {
		os.Setenv("DATABASE_URL", oldURL)
		os.Setenv("DB_HOST", oldHost)
		os.Setenv("DB_USER", oldUser)
		os.Setenv("DB_PASSWORD", oldPass)
		os.Setenv("DB_NAME", oldName)
		os.Setenv("DB_PORT", oldPort)
		os.Setenv("DB_SSLMODE", oldSSL)
	}()

	// Case 1: DATABASE_URL
	os.Setenv("DATABASE_URL", "postgres://foo:bar@localhost:5432/db?sslmode=disable")
	s, err := database.BuildConnectionString()
	if err != nil {
		t.Errorf("Unexpected error: %v", err)
	}
	if s != "postgres://foo:bar@localhost:5432/db?sslmode=disable" {
		t.Errorf("Mismatch URL")
	}

	// Case 2: Individual Params
	os.Unsetenv("DATABASE_URL")
	os.Setenv("DB_HOST", "localhost")
	os.Setenv("DB_USER", "user")
	os.Setenv("DB_PASSWORD", "pass")
	os.Setenv("DB_NAME", "mydb")
	os.Setenv("DB_PORT", "5432")
	os.Setenv("DB_SSLMODE", "disable")

	s, err = database.BuildConnectionString()
	if err != nil {
		t.Errorf("Unexpected error: %v", err)
	}
	expected := "host=localhost port=5432 user=user password=pass dbname=mydb sslmode=disable"
	if s != expected {
		t.Errorf("Expected %s, got %s", expected, s)
	}

	// Case 3: Missing Param
	os.Unsetenv("DB_HOST")
	_, err = database.BuildConnectionString()
	if err == nil {
		t.Error("Expected error for missing host")
	}
}

func TestRunMigrations(t *testing.T) {
	// Setup Mock DB
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
	}
	defer db.Close()

	// Inject DB
	database.DB = db

	// Create temp migrations dir
	err = os.Mkdir("migrations", 0755)
	if err != nil && !os.IsExist(err) {
		t.Fatalf("Failed to create migrations dir: %v", err)
	}
	defer os.RemoveAll("migrations")

	// Create dummy migration file
	content := "CREATE TABLE test (id int);"
	err = os.WriteFile("migrations/001_test.sql", []byte(content), 0644)
	if err != nil {
		t.Fatalf("Failed to write migration file: %v", err)
	}

	// Mock Expectation
	mock.ExpectExec(regexp.QuoteMeta(content)).WillReturnResult(sqlmock.NewResult(0, 0))

	// Run
	database.RunMigrations()

	if err := mock.ExpectationsWereMet(); err != nil {
		t.Errorf("there were unfulfilled expectations: %s", err)
	}
}
