package bootstrap

import (
	"baron-sso-backend/internal/domain"
	"log/slog"
	"os"
	"strings"
	"time"
)

// SeedAdminIdentity creates the initial admin identity in the configured IDP.
// Returns the Kratos Identity ID and error.
func SeedAdminIdentity(idp domain.IdentityProvider) (string, error) {
	if idp == nil {
		return "", nil
	}

	adminEmail := strings.TrimSpace(os.Getenv("ADMIN_EMAIL"))
	adminPassword := os.Getenv("ADMIN_PASSWORD")
	if adminEmail == "" || adminPassword == "" {
		slog.Warn("[Bootstrap] ADMIN_EMAIL or ADMIN_PASSWORD not set. Skipping admin identity seed.")
		return "", nil
	}

	adminName := strings.TrimSpace(os.Getenv("ADMIN_NAME"))
	if adminName == "" {
		adminName = "System Admin"
	}

	user := &domain.BrokerUser{
		Email:       adminEmail,
		Name:        adminName,
		PhoneNumber: "",
		Attributes: map[string]any{
			"department":      "Admin",
			"affiliationType": "internal",
			"grade":           "",
			"role":            "super_admin", // Explicitly set role for Kratos traits
		},
	}

	// Retry logic for Kratos connection
	maxRetries := 5
	var err error
	var identityID string

	for i := range maxRetries {
		identityID, err = idp.CreateUser(user, adminPassword)
		if err == nil {
			slog.Info("[Bootstrap] Admin identity created in IDP", "email", adminEmail, "idp", idp.Name(), "id", identityID)
			return identityID, nil
		}

		if strings.Contains(err.Error(), "already exists") {
			slog.Info("[Bootstrap] Admin identity already exists in IDP. Attempting to retrieve ID...", "email", adminEmail)
			// Try to sign in to get the identity ID
			authInfo, err := idp.SignIn(adminEmail, adminPassword)
			if err == nil && authInfo != nil {
				slog.Info("[Bootstrap] Retrieved existing admin identity ID", "id", authInfo.Subject)
				return authInfo.Subject, nil
			}
			slog.Warn("[Bootstrap] Failed to retrieve existing admin identity ID via SignIn", "error", err)
			return "", nil // Return nil error to avoid stopping bootstrap, but ID is missing
		}

		slog.Warn("[Bootstrap] Failed to seed admin identity (retrying...)",
			"attempt", i+1,
			"max_retries", maxRetries,
			"error", err,
		)
		time.Sleep(2 * time.Second)
	}

	return "", err
}
