package dashboard

import (
	"context"
	"errors"
	"testing"

	"github.com/nexuscrm/shared/pkg/models"
)

func TestEffectiveUserPolicyResolvesSpecifiedRunningUserThroughSessionLoader(t *testing.T) {
	viewer := &models.UserSession{ID: "viewer"}
	email := "running@example.com"
	roleID := "role-1"
	runningUser := &models.UserSession{
		ID:        "running-user",
		Name:      "Run Ning",
		Email:     &email,
		ProfileID: "profile-1",
		RoleID:    &roleID,
	}
	loader := &dashboardPolicySessionLoader{result: runningUser}
	policy := NewEffectiveUserPolicy(loader, nil)

	got, err := policy.EffectiveUser(context.Background(), DashboardEffectiveUserRequest{
		DashboardID: "dash-1",
		Definition: &Definition{
			DashboardType: "SpecifiedUser",
			RunningUserId: "running-user",
		},
		Viewer: viewer,
	})
	if err != nil {
		t.Fatalf("EffectiveUser returned error: %v", err)
	}

	if got != runningUser {
		t.Fatalf("effective user = %#v, want session loader result", got)
	}
	if loader.userID != "running-user" {
		t.Fatalf("loaded user id = %q, want running-user", loader.userID)
	}
}

func TestEffectiveUserPolicyFallsBackToViewerWhenSessionLoaderRejectsRunningUser(t *testing.T) {
	viewer := &models.UserSession{ID: "viewer"}
	loader := &dashboardPolicySessionLoader{err: errors.New("user is inactive")}
	policy := NewEffectiveUserPolicy(loader, nil)

	got, err := policy.EffectiveUser(context.Background(), DashboardEffectiveUserRequest{
		DashboardID: "dash-1",
		Definition: &Definition{
			DashboardType: "SpecifiedUser",
			RunningUserId: "running-user",
		},
		Viewer: viewer,
	})
	if err != nil {
		t.Fatalf("EffectiveUser returned error: %v", err)
	}

	if got != viewer {
		t.Fatalf("effective user = %#v, want viewer fallback when loader rejects running user", got)
	}
	if loader.userID != "running-user" {
		t.Fatalf("loaded user id = %q, want running-user", loader.userID)
	}
}

type dashboardPolicySessionLoader struct {
	userID string
	result *models.UserSession
	err    error
}

func (l *dashboardPolicySessionLoader) LoadUserSession(ctx context.Context, userID string) (*models.UserSession, error) {
	l.userID = userID
	return l.result, l.err
}
