package bootstrap

import (
	"baron-sso-backend/internal/domain"
	"errors"
	"fmt"
	"log/slog"
	"os"

	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
)

// Run executes the application bootstrap logic (migrations, seeding, etc.)
func Run(db *gorm.DB) error {
	slog.Info("[Bootstrap] Starting application bootstrap...")

	// 1. Auto Migration
	if err := migrateSchemas(db); err != nil {
		return fmt.Errorf("migration failed: %w", err)
	}

	// 2. Seed Initial Admin User
	if err := seedAdminUser(db); err != nil {
		return fmt.Errorf("seeding admin failed: %w", err)
	}

	slog.Info("[Bootstrap] Bootstrap completed successfully.")
	return nil
}

func migrateSchemas(db *gorm.DB) error {
	slog.Info("[Bootstrap] Migrating database schemas...")
	// Add all domain models here
	return db.AutoMigrate(
		&domain.User{},
		&domain.Tenant{},
		// &domain.RelyingParty{}, // TODO: Uncomment when model is ready
		// &domain.UserConsent{},  // TODO: Uncomment when model is ready
	)
}

func seedAdminUser(db *gorm.DB) error {
	adminEmail := os.Getenv("ADMIN_EMAIL")
	adminPassword := os.Getenv("ADMIN_PASSWORD")

	if adminEmail == "" || adminPassword == "" {
		slog.Warn("[Bootstrap] ADMIN_EMAIL or ADMIN_PASSWORD not set. Skipping admin seeding.")
		return nil
	}

	var user domain.User
	if err := db.Where("email = ?", adminEmail).First(&user).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			slog.Info("[Bootstrap] Creating initial admin user", "email", adminEmail)

			hashedPassword, err := bcrypt.GenerateFromPassword([]byte(adminPassword), bcrypt.DefaultCost)
			if err != nil {
				return err
			}

			adminUser := domain.User{
				Email:        adminEmail,
				PasswordHash: string(hashedPassword),
				Name:         "System Admin",
				Role:         "admin", // Assuming 'role' field exists or handling via attributes
				// Add other required fields
			}

			if err := db.Create(&adminUser).Error; err != nil {
				return err
			}
			slog.Info("[Bootstrap] Admin user created successfully.")
		} else {
			return err
		}
	} else {
		slog.Info("[Bootstrap] Admin user already exists.", "email", adminEmail)
	}

	return nil
}
