// Package bus provides the bus_send tool, which lets an agent's LLM post a
// message into a unibus room. It replaces the former matrix_send tool now that
// the ecosystem speaks only over the message bus.
package bus

import (
	"context"
	"fmt"

	"github.com/enmanuel/agents/internal/config"
	"github.com/enmanuel/agents/tools"
)

// Sender is the message-sending capability the bus_send tool needs. It is
// satisfied by the unibus bus sender used throughout the agent shell.
type Sender interface {
	SendMarkdown(ctx context.Context, roomID, markdown string) error
}

// NewBusSend creates a bus_send tool that posts a message to a unibus room.
// If AllowedRooms is configured, only those room IDs can be targeted.
func NewBusSend(sender Sender, cfg config.BusToolCfg) tools.Tool {
	return tools.Tool{
		Def: tools.Def{
			Name:        "bus_send",
			Description: "Send a text message to a unibus room.",
			Parameters: []tools.Param{
				{Name: "room_id", Type: "string", Description: "The unibus room ID to send to", Required: true},
				{Name: "message", Type: "string", Description: "The text message to send", Required: true},
			},
		},
		Exec: func(ctx context.Context, args map[string]any) tools.Result {
			roomID := tools.GetString(args, "room_id")
			message := tools.GetString(args, "message")
			if roomID == "" || message == "" {
				return tools.Result{Err: fmt.Errorf("bus_send: room_id and message are required")}
			}

			if err := validateRoom(roomID, cfg.AllowedRooms); err != nil {
				return tools.Result{Err: err}
			}

			if err := sender.SendMarkdown(ctx, roomID, message); err != nil {
				return tools.Result{Err: fmt.Errorf("bus_send: %w", err)}
			}

			return tools.Result{Output: fmt.Sprintf("message sent to %s", roomID)}
		},
	}
}

// validateRoom checks that roomID is in the allowed list.
// If allowedRooms is empty, all rooms are allowed.
func validateRoom(roomID string, allowedRooms []string) error {
	if len(allowedRooms) == 0 {
		return nil
	}
	for _, r := range allowedRooms {
		if roomID == r {
			return nil
		}
	}
	return fmt.Errorf("bus_send: room %q not in allowed rooms list", roomID)
}
