package routing

import (
	"errors"
	"testing"

	"git.mleku.dev/mleku/nostr/encoders/event"
)

func TestNew(t *testing.T) {
	r := New()
	if r == nil {
		t.Fatal("New() returned nil")
	}
	if r.handlers == nil {
		t.Fatal("handlers map is nil")
	}
	if r.kindChecks == nil {
		t.Fatal("kindChecks slice is nil")
	}
}

func TestResultConstructors(t *testing.T) {
	// ContinueResult
	r := ContinueResult()
	if r.Action != Continue {
		t.Error("ContinueResult should have Action=Continue")
	}

	// HandledResult
	r = HandledResult("success")
	if r.Action != Handled {
		t.Error("HandledResult should have Action=Handled")
	}
	if r.Message != "success" {
		t.Error("HandledResult should preserve message")
	}

	// ErrorResult
	err := errors.New("test error")
	r = ErrorResult(err)
	if r.Action != Error {
		t.Error("ErrorResult should have Action=Error")
	}
	if r.Error != err {
		t.Error("ErrorResult should preserve error")
	}
}

func TestDefaultRouter_Register(t *testing.T) {
	r := New()

	called := false
	handler := func(ev *event.E, authedPubkey []byte) Result {
		called = true
		return HandledResult("handled")
	}

	r.Register(1, handler)

	ev := event.New()
	ev.Kind = 1

	result := r.Route(ev, nil)
	if !called {
		t.Error("handler should have been called")
	}
	if result.Action != Handled {
		t.Error("result should be Handled")
	}
}

func TestDefaultRouter_RegisterKindCheck(t *testing.T) {
	r := New()

	called := false
	handler := func(ev *event.E, authedPubkey []byte) Result {
		called = true
		return HandledResult("ephemeral")
	}

	// Register handler for ephemeral events (20000-29999)
	r.RegisterKindCheck("ephemeral", func(k uint16) bool {
		return k >= 20000 && k < 30000
	}, handler)

	ev := event.New()
	ev.Kind = 20001

	result := r.Route(ev, nil)
	if !called {
		t.Error("kind check handler should have been called")
	}
	if result.Action != Handled {
		t.Error("result should be Handled")
	}
}

func TestDefaultRouter_NoMatch(t *testing.T) {
	r := New()

	// Register handler for kind 1
	r.Register(1, func(ev *event.E, authedPubkey []byte) Result {
		return HandledResult("kind 1")
	})

	ev := event.New()
	ev.Kind = 2 // Different kind

	result := r.Route(ev, nil)
	if result.Action != Continue {
		t.Error("unmatched kind should return Continue")
	}
}

func TestDefaultRouter_ExactMatchPriority(t *testing.T) {
	r := New()

	exactCalled := false
	checkCalled := false

	// Register exact match for kind 20001
	r.Register(20001, func(ev *event.E, authedPubkey []byte) Result {
		exactCalled = true
		return HandledResult("exact")
	})

	// Register kind check for ephemeral (also matches 20001)
	r.RegisterKindCheck("ephemeral", func(k uint16) bool {
		return k >= 20000 && k < 30000
	}, func(ev *event.E, authedPubkey []byte) Result {
		checkCalled = true
		return HandledResult("check")
	})

	ev := event.New()
	ev.Kind = 20001

	result := r.Route(ev, nil)
	if !exactCalled {
		t.Error("exact match should be called")
	}
	if checkCalled {
		t.Error("kind check should not be called when exact match exists")
	}
	if result.Message != "exact" {
		t.Errorf("expected 'exact', got '%s'", result.Message)
	}
}

func TestDefaultRouter_HasHandler(t *testing.T) {
	r := New()

	// Initially no handlers
	if r.HasHandler(1) {
		t.Error("should not have handler for kind 1 yet")
	}

	// Register exact handler
	r.Register(1, func(ev *event.E, authedPubkey []byte) Result {
		return HandledResult("")
	})

	if !r.HasHandler(1) {
		t.Error("should have handler for kind 1")
	}

	// Register kind check for ephemeral
	r.RegisterKindCheck("ephemeral", func(k uint16) bool {
		return k >= 20000 && k < 30000
	}, func(ev *event.E, authedPubkey []byte) Result {
		return HandledResult("")
	})

	if !r.HasHandler(20001) {
		t.Error("should have handler for ephemeral kind 20001")
	}

	if r.HasHandler(19999) {
		t.Error("should not have handler for kind 19999")
	}
}

func TestDefaultRouter_PassesPubkey(t *testing.T) {
	r := New()

	var receivedPubkey []byte
	r.Register(1, func(ev *event.E, authedPubkey []byte) Result {
		receivedPubkey = authedPubkey
		return HandledResult("")
	})

	testPubkey := []byte("testpubkey12345")
	ev := event.New()
	ev.Kind = 1

	r.Route(ev, testPubkey)

	if string(receivedPubkey) != string(testPubkey) {
		t.Error("handler should receive the authed pubkey")
	}
}

func TestDefaultRouter_MultipleKindChecks(t *testing.T) {
	r := New()

	firstCalled := false
	secondCalled := false

	// First check matches 10000-19999
	r.RegisterKindCheck("first", func(k uint16) bool {
		return k >= 10000 && k < 20000
	}, func(ev *event.E, authedPubkey []byte) Result {
		firstCalled = true
		return HandledResult("first")
	})

	// Second check matches 15000-25000 (overlaps)
	r.RegisterKindCheck("second", func(k uint16) bool {
		return k >= 15000 && k < 25000
	}, func(ev *event.E, authedPubkey []byte) Result {
		secondCalled = true
		return HandledResult("second")
	})

	// Kind 15000 matches both - first registered wins
	ev := event.New()
	ev.Kind = 15000

	result := r.Route(ev, nil)
	if !firstCalled {
		t.Error("first check should be called")
	}
	if secondCalled {
		t.Error("second check should not be called")
	}
	if result.Message != "first" {
		t.Errorf("expected 'first', got '%s'", result.Message)
	}
}
