package permissions

import (
	"context"
	"errors"
	"strings"
	"testing"

	"github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/permissionauthoringv1"
)

func TestStrictPermissionAuthoringAuditWriterUsesOneFailClosedAggregateRow(t *testing.T) {
	store := &permissionAuthoringAuditStoreForTest{}
	writer, err := NewStrictPermissionAuthoringAuditWriter(store)
	if err != nil {
		t.Fatal(err)
	}
	event := PermissionAuthoringAuditEvent{
		CommandID: "permission-save:1", CommandDigest: "sha256:abc", ActorID: "user-1",
		SelectedTargetKind: permissionauthoringv1.TargetProfile, SelectedTargetID: "profile-1",
		CanonicalPermissionSet: "permission-set-1",
		AuthoringRevision:      42,
		FinalChanges: permissionauthoringv1.Changes{
			System: []permissionauthoringv1.CapabilityGrantChange{{CapabilityID: "ApiEnabled", Enabled: true}},
		},
	}
	if err := writer.WritePermissionAuthoringAudit(t.Context(), event); err != nil {
		t.Fatalf("WritePermissionAuthoringAudit(): %v", err)
	}
	if store.calls != 1 || store.action != permissionAuthoringAuditAction ||
		store.section != permissionAuthoringAuditSection || store.userID != "user-1" {
		t.Fatalf("audit store call = %+v", store)
	}
	for _, fact := range []string{event.CommandID, event.CommandDigest, string(event.SelectedTargetKind), event.SelectedTargetID, event.CanonicalPermissionSet} {
		if !strings.Contains(store.display, fact) {
			t.Fatalf("audit display %q omits %q", store.display, fact)
		}
	}
	for _, fact := range []string{"ApiEnabled", `"enabled":true`, `"authoring_revision":42`, `"final_changes"`} {
		if !strings.Contains(store.display, fact) {
			t.Fatalf("audit display %q omits semantic fact %q", store.display, fact)
		}
	}

	store.err = errors.New("audit insert failed")
	if err := writer.WritePermissionAuthoringAudit(t.Context(), event); !errors.Is(err, store.err) {
		t.Fatalf("WritePermissionAuthoringAudit(error) = %v", err)
	}
}

type permissionAuthoringAuditStoreForTest struct {
	calls                    int
	action, section, display string
	userID                   string
	err                      error
}

func (s *permissionAuthoringAuditStoreForTest) RecordSetupChange(_ context.Context, action, section, display, userID string) error {
	s.calls++
	s.action, s.section, s.display, s.userID = action, section, display, userID
	return s.err
}
