package mru

import (
	"context"
	"testing"

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

func TestContractSearchScopeCuratedObjectNamesUsesPackOrderAndReadAccess(t *testing.T) {
	scope := &contractSearchScope{
		metadata: fakeSearchScopeMetadata{
			packObjects: []string{"Lead", "Account", "Contact"},
			scopeObjects: []string{
				"Contact",
				"Opportunity",
			},
		},
		permissions: fakeSearchScopePermissionChecker{
			allowed: map[string]bool{
				"Lead":    true,
				"Account": false,
				"Contact": true,
			},
		},
	}

	got := scope.CuratedObjectNames(context.Background(), &models.UserSession{ID: "005xx"})
	want := []string{"Lead", "Contact"}
	assertStringSlice(t, got, want)
}

func TestContractSearchScopeCuratedObjectNamesDoesNotAppendMetadataFallback(t *testing.T) {
	scope := &contractSearchScope{
		metadata: fakeSearchScopeMetadata{
			packObjects: []string{"Account"},
			scopeObjects: []string{
				"Account",
				"Contact",
			},
		},
		permissions: fakeSearchScopePermissionChecker{
			allowed: map[string]bool{
				"Account": true,
				"Contact": true,
			},
		},
	}

	got := scope.CuratedObjectNames(context.Background(), &models.UserSession{ID: "005xx"})
	want := []string{"Account"}
	assertStringSlice(t, got, want)
}

type fakeSearchScopeMetadata struct {
	scopeObjects []string
	packObjects  []string
}

func (f fakeSearchScopeMetadata) GetSearchScopeObjects(context.Context) []string {
	return append([]string(nil), f.scopeObjects...)
}

func (f fakeSearchScopeMetadata) PackSearchScopeObjectNames(context.Context) []string {
	return append([]string(nil), f.packObjects...)
}

type fakeSearchScopePermissionChecker struct {
	allowed map[string]bool
}

func (f fakeSearchScopePermissionChecker) CheckObjectPermissionWithUser(_ context.Context, objectAPIName string, operation string, _ *models.UserSession) bool {
	if operation != constants.PermRead {
		return false
	}
	return f.allowed[objectAPIName]
}

func assertStringSlice(t *testing.T, got []string, want []string) {
	t.Helper()
	if len(got) != len(want) {
		t.Fatalf("len = %d, want %d (got=%v)", len(got), len(want), got)
	}
	for i := range want {
		if got[i] != want[i] {
			t.Fatalf("[%d] = %q, want %q (got=%v)", i, got[i], want[i], got)
		}
	}
}
