// Package routing provides event routing services for the ORLY relay.
// It dispatches events to specialized handlers based on event kind.
package routing

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

// Action indicates what to do after routing.
type Action int

const (
	// Continue means continue to normal processing.
	Continue Action = iota
	// Handled means event was fully handled, return success.
	Handled
	// Error means an error occurred.
	Error
)

// Result contains the routing decision.
type Result struct {
	Action  Action
	Message string // Success or error message
	Error   error  // Error if Action == Error
}

// ContinueResult returns a result indicating normal processing should continue.
func ContinueResult() Result {
	return Result{Action: Continue}
}

// HandledResult returns a result indicating the event was fully handled.
func HandledResult(msg string) Result {
	return Result{Action: Handled, Message: msg}
}

// ErrorResult returns a result indicating an error occurred.
func ErrorResult(err error) Result {
	return Result{Action: Error, Error: err}
}

// Handler processes a specific event kind.
// authedPubkey is the authenticated pubkey of the connection (may be nil).
type Handler func(ev *event.E, authedPubkey []byte) Result

// KindCheck tests whether an event kind matches a category (e.g., ephemeral).
type KindCheck struct {
	Name    string
	Check   func(kind uint16) bool
	Handler Handler
}

// Router dispatches events to specialized handlers.
type Router interface {
	// Route checks if event should be handled specially.
	Route(ev *event.E, authedPubkey []byte) Result

	// Register adds a handler for a specific kind.
	Register(kind uint16, handler Handler)

	// RegisterKindCheck adds a handler for a kind category.
	RegisterKindCheck(name string, check func(uint16) bool, handler Handler)
}

// DefaultRouter implements Router with a handler registry.
type DefaultRouter struct {
	handlers   map[uint16]Handler
	kindChecks []KindCheck
}

// New creates a new DefaultRouter.
func New() *DefaultRouter {
	return &DefaultRouter{
		handlers:   make(map[uint16]Handler),
		kindChecks: make([]KindCheck, 0),
	}
}

// Register adds a handler for a specific kind.
func (r *DefaultRouter) Register(kind uint16, handler Handler) {
	r.handlers[kind] = handler
}

// RegisterKindCheck adds a handler for a kind category.
func (r *DefaultRouter) RegisterKindCheck(name string, check func(uint16) bool, handler Handler) {
	r.kindChecks = append(r.kindChecks, KindCheck{
		Name:    name,
		Check:   check,
		Handler: handler,
	})
}

// Route checks if event should be handled specially.
func (r *DefaultRouter) Route(ev *event.E, authedPubkey []byte) Result {
	// Check exact kind matches first (higher priority)
	if handler, ok := r.handlers[ev.Kind]; ok {
		return handler(ev, authedPubkey)
	}

	// Check kind property handlers (ephemeral, replaceable, etc.)
	for _, kc := range r.kindChecks {
		if kc.Check(ev.Kind) {
			return kc.Handler(ev, authedPubkey)
		}
	}

	return ContinueResult()
}

// HasHandler returns true if a handler is registered for the given kind.
func (r *DefaultRouter) HasHandler(kind uint16) bool {
	if _, ok := r.handlers[kind]; ok {
		return true
	}
	for _, kc := range r.kindChecks {
		if kc.Check(kind) {
			return true
		}
	}
	return false
}
