package lib

import (
	"fmt"

	"github.com/bwmarrin/discordgo"
)

// Represents a function that processes a message
type MessageProcessor func(s *discordgo.Session, m *discordgo.MessageCreate, ctx *ProcessContext) error

// Holds shared data between processors
type ProcessContext struct {
	UserID      int
	GuildID     string
	DiscordUser *discordgo.User
}

// Handles the registration and execution of message processors
type MessageProcessorManager struct {
	processors []MessageProcessor
}

// Creates a new MessageProcessorManager
func NewMessageProcessorManager() *MessageProcessorManager {
	return &MessageProcessorManager{
		processors: make([]MessageProcessor, 0),
	}
}

// Adds a new message processor to the manager
func (pm *MessageProcessorManager) RegisterProcessor(processor MessageProcessor) {
	pm.processors = append(pm.processors, processor)
}

// Runs all registered processors on a message
func (pm *MessageProcessorManager) ProcessMessage(s *discordgo.Session, m *discordgo.MessageCreate) {
	if m.Author.Bot {
		return
	}

	// Create processing context
	ctx := &ProcessContext{
		GuildID:     m.GuildID,
		DiscordUser: m.Author,
	}

	// Get or create user and guild profile together
	userID, err := GetOrCreateUserWithGuild(m.Author.ID, m.Author.Username, m.GuildID)
	if err != nil {
		ThrowWithError("MessageProcessor", fmt.Sprintf("failed to handle user and guild profile: %v", err))
		return
	}

	ctx.UserID = userID

	// Run each processor with the context
	for _, processor := range pm.processors {
		if err := processor(s, m, ctx); err != nil {
			ThrowWithError("MessageProcessor", err.Error())
		}
	}
}
