package rules

import (
	"testing"
	"time"

	"github.com/nexuscrm/sentry/internal/types"
)

// fakeRule implements Rule for testing the engine's dispatch.
type fakeRule struct {
	id      string
	results []types.RuleResult
}

func (f *fakeRule) ID() string { return f.id }
func (f *fakeRule) Evaluate(current types.Snapshot, history HistoryFinder) []types.RuleResult {
	return f.results
}

// nilHistory returns no snapshots — used when rules don't need history.
type nilHistory struct{}

func (nilHistory) FindClosest(_ time.Time, _ int64) (types.Snapshot, bool) {
	return types.Snapshot{}, false
}

func TestEngine_NoRules(t *testing.T) {
	eng := NewEngine(nil)
	snap := types.Snapshot{SnapshotTs: time.Now(), EpochID: 1}
	if got := eng.Evaluate(snap, nilHistory{}); len(got) != 0 {
		t.Errorf("expected 0 results, got %d", len(got))
	}
}

func TestEngine_CollectsFromAllRules(t *testing.T) {
	eng := NewEngine([]Rule{
		&fakeRule{id: "r1", results: []types.RuleResult{{RuleID: "r1", Entity: "a", Level: "WARN", Breached: true}}},
		&fakeRule{id: "r2", results: nil}, // quiet rule
		&fakeRule{id: "r3", results: []types.RuleResult{
			{RuleID: "r3", Entity: "b", Level: "CRIT", Breached: true},
			{RuleID: "r3", Entity: "c", Level: "WARN", Breached: true},
		}},
	})
	snap := types.Snapshot{SnapshotTs: time.Now(), EpochID: 1}
	results := eng.Evaluate(snap, nilHistory{})
	if len(results) != 3 {
		t.Fatalf("expected 3 results, got %d", len(results))
	}
	// Order preserved: r1 first, then r3's two
	if results[0].RuleID != "r1" || results[1].RuleID != "r3" || results[2].RuleID != "r3" {
		t.Errorf("order wrong: %+v", results)
	}
}
