package migration

import (
	"context"
	"strings"
)

// OnboardingHints guides the user-facing migration setup flow.
type OnboardingHints struct {
	NeedsUserOAuth             bool   `json:"needs_user_oauth"`
	OAuthProvider              string `json:"oauth_provider,omitempty"`
	WaitingForAdmin            bool   `json:"waiting_for_admin"`
	WaitingReason              string `json:"waiting_reason,omitempty"`
	HasMigrationCredentials    bool   `json:"has_migration_credentials"`
	NeedsMicrosoftAdminConsent bool   `json:"needs_microsoft_admin_consent,omitempty"`
}

func (s *Service) BuildOnboardingHints(ctx context.Context, userID string, proj Project, invite Invite) OnboardingHints {
	h := OnboardingHints{
		OAuthProvider: proj.SourceProvider,
	}

	switch proj.Status {
	case "active", "cutover":
		// worker eligible
	default:
		h.WaitingForAdmin = true
		if proj.Status == "draft" {
			h.WaitingReason = "project_not_activated"
		} else {
			h.WaitingReason = "project_status_" + proj.Status
		}
	}

	if UsesUserOAuth(proj.SourceProvider, proj.AuthMode) {
		h.NeedsUserOAuth = true
		if userID != "" {
			hasCred, err := s.hasMigrationCredential(ctx, userID, proj.ID, proj.SourceProvider)
			if err == nil {
				h.HasMigrationCredentials = hasCred
			}
		}
	}

	if proj.SourceProvider == "microsoft" && proj.MicrosoftAdminConsentAt == nil {
		h.NeedsMicrosoftAdminConsent = true
	}

	if invite.Status == "claimed" && h.WaitingForAdmin {
		h.WaitingReason = waitingReasonMessage(h.WaitingReason)
	}

	return h
}

func waitingReasonMessage(code string) string {
	switch code {
	case "project_not_activated":
		return "project_not_activated"
	default:
		return code
	}
}

func (s *Service) hasMigrationCredential(ctx context.Context, userID, projectID, provider string) (bool, error) {
	provider = strings.ToLower(strings.TrimSpace(provider))
	if provider == "" {
		return false, nil
	}
	var exists bool
	err := s.db.QueryRow(ctx, `
		SELECT EXISTS(
			SELECT 1 FROM migration_credentials
			WHERE user_id = $1::uuid AND project_id = $2::uuid AND provider = $3 AND revoked_at IS NULL
		)
	`, userID, projectID, provider).Scan(&exists)
	return exists, err
}

func (s *Service) BuildInviteOnboardingHints(proj Project, invite Invite) OnboardingHints {
	h := OnboardingHints{OAuthProvider: proj.SourceProvider}
	if invite.Status == "claimed" {
		h.NeedsUserOAuth = UsesUserOAuth(proj.SourceProvider, proj.AuthMode)
		return h
	}
	if UsesUserOAuth(proj.SourceProvider, proj.AuthMode) {
		h.NeedsUserOAuth = true
	}
	if proj.SourceProvider == "microsoft" && proj.MicrosoftAdminConsentAt == nil {
		h.NeedsMicrosoftAdminConsent = true
	}
	return h
}
