package devagents

import (
	"sort"
	"testing"

	"github.com/enmanuel/agents/pkg/decision"
)

func TestRegisterAndGetRules(t *testing.T) {
	resetRegistry()

	called := false
	fn := func() []decision.Rule {
		called = true
		return []decision.Rule{{Name: "test-rule"}}
	}

	Register("test-agent", fn)

	got := GetRules("test-agent")
	if got == nil {
		t.Fatal("GetRules returned nil for registered agent")
	}

	rules := got()
	if !called {
		t.Error("rule factory was not called")
	}
	if len(rules) != 1 || rules[0].Name != "test-rule" {
		t.Errorf("unexpected rules: %+v", rules)
	}
}

func TestGetRulesMissing(t *testing.T) {
	resetRegistry()

	got := GetRules("nonexistent")
	if got != nil {
		t.Errorf("expected nil for unregistered agent, got %v", got)
	}
}

func TestRegisterDuplicatePanics(t *testing.T) {
	resetRegistry()

	fn := func() []decision.Rule { return nil }
	Register("dup-agent", fn)

	defer func() {
		r := recover()
		if r == nil {
			t.Fatal("expected panic on duplicate registration, got none")
		}
		msg, ok := r.(string)
		if !ok {
			t.Fatalf("expected string panic, got %T: %v", r, r)
		}
		if msg != "agents.Register: duplicate agent id: dup-agent" {
			t.Errorf("unexpected panic message: %s", msg)
		}
	}()

	Register("dup-agent", fn)
}

func TestRegisteredIDs(t *testing.T) {
	resetRegistry()

	Register("charlie", func() []decision.Rule { return nil })
	Register("alpha", func() []decision.Rule { return nil })
	Register("bravo", func() []decision.Rule { return nil })

	ids := RegisteredIDs()
	sort.Strings(ids)

	expected := []string{"alpha", "bravo", "charlie"}
	if len(ids) != len(expected) {
		t.Fatalf("expected %d ids, got %d: %v", len(expected), len(ids), ids)
	}
	for i, id := range ids {
		if id != expected[i] {
			t.Errorf("id[%d] = %q, want %q", i, id, expected[i])
		}
	}
}

func TestResetRegistry(t *testing.T) {
	resetRegistry()

	Register("temp", func() []decision.Rule { return nil })
	if GetRules("temp") == nil {
		t.Fatal("expected registered agent")
	}

	resetRegistry()

	if GetRules("temp") != nil {
		t.Error("expected nil after reset")
	}
	if len(RegisteredIDs()) != 0 {
		t.Error("expected empty registry after reset")
	}
}
