package services

import (
	"slices"
	"testing"
)

// t-paliad-249 — Slice A. Ensures the *_approval_* audit kinds are
// dropped from the project_event read path when ApprovalRequest is
// also fanning out, so the same fact isn't shown twice in /inbox.

func TestAllowedProjectEventKinds_DedupsApprovalAudits(t *testing.T) {
	spec := FilterSpec{
		Version: SpecVersion,
		Sources: []DataSource{SourceApprovalRequest, SourceProjectEvent},
		Predicates: &Predicates{
			ProjectEvent: &ProjectEventPredicates{
				EventTypes: []string{
					"deadline_created",
					"deadline_approval_requested",
					"appointment_approval_approved",
					"approval_decided",
					"note_created",
				},
			},
		},
	}
	got := allowedProjectEventKinds(spec)
	if slices.Contains(got, "deadline_approval_requested") {
		t.Errorf("must drop deadline_approval_requested, got %v", got)
	}
	if slices.Contains(got, "appointment_approval_approved") {
		t.Errorf("must drop appointment_approval_approved, got %v", got)
	}
	if slices.Contains(got, "approval_decided") {
		t.Errorf("must drop approval_decided, got %v", got)
	}
	if !slices.Contains(got, "deadline_created") {
		t.Errorf("must keep deadline_created, got %v", got)
	}
	if !slices.Contains(got, "note_created") {
		t.Errorf("must keep note_created, got %v", got)
	}
}

func TestAllowedProjectEventKinds_NoDedupWhenApprovalsAbsent(t *testing.T) {
	spec := FilterSpec{
		Version: SpecVersion,
		Sources: []DataSource{SourceProjectEvent},
		Predicates: &Predicates{
			ProjectEvent: &ProjectEventPredicates{
				EventTypes: []string{
					"deadline_created",
					"deadline_approval_requested",
				},
			},
		},
	}
	got := allowedProjectEventKinds(spec)
	if !slices.Contains(got, "deadline_approval_requested") {
		t.Errorf("Verlauf-style spec without approvals source should keep audit kinds, got %v", got)
	}
}

func TestAllowedProjectEventKinds_NilWhenNoPredicateAndNoDedup(t *testing.T) {
	spec := FilterSpec{
		Version: SpecVersion,
		Sources: []DataSource{SourceProjectEvent},
	}
	if got := allowedProjectEventKinds(spec); got != nil {
		t.Errorf("expected nil (all kinds), got %v", got)
	}
}

func TestAllowedProjectEventKinds_FillsImplicitListWhenDedup(t *testing.T) {
	// When approvals are in sources but the caller didn't explicitly
	// narrow EventTypes, the helper must materialise the curated set
	// minus audit duplicates so the WHERE clause filters them out.
	spec := FilterSpec{
		Version: SpecVersion,
		Sources: []DataSource{SourceApprovalRequest, SourceProjectEvent},
	}
	got := allowedProjectEventKinds(spec)
	if got == nil {
		t.Fatal("expected explicit kind list, got nil")
	}
	for _, k := range got {
		if isApprovalAuditKind(k) {
			t.Errorf("audit kind %q leaked through dedup", k)
		}
	}
}

func TestIsApprovalAuditKind(t *testing.T) {
	cases := map[string]bool{
		"deadline_approval_requested":       true,
		"appointment_approval_approved":     true,
		"appointment_approval_rejected":     true,
		"deadline_approval_changes_suggested": true,
		"approval_decided":                  true,
		"deadline_created":                  false,
		"note_created":                      false,
		"our_side_changed":                  false,
		"project_archived":                  false,
	}
	for kind, want := range cases {
		if got := isApprovalAuditKind(kind); got != want {
			t.Errorf("isApprovalAuditKind(%q) = %v, want %v", kind, got, want)
		}
	}
}
