package chat

import (
	"bytes"
	"log/slog"

	"github.com/nicklaw5/helix/v2"

	"git.sr.ht/~ashkeel/strimertul/log"
)

var accessLevels = map[AccessLevelType]int{
	ALTEveryone:    0,
	ALTSubscribers: 1,
	ALTVIP:         2,
	ALTModerators:  3,
	ALTStreamer:    999,
}

type CommandHandler func(message helix.EventSubChannelChatMessageEvent)

type Command struct {
	Description string
	Usage       string
	AccessLevel AccessLevelType
	Handler     CommandHandler
	Enabled     bool
}

func getUserAccessLevel(badges []helix.EventSubChatBadge) AccessLevelType {
	// Read badges
	var broadcaster, moderator, vip, subscriber bool
	for _, badge := range badges {
		switch badge.SetID {
		case "broadcaster":
			broadcaster = true
		case "moderator":
			moderator = true
		case "vip":
			vip = true
		case "subscriber":
			subscriber = true
		}
	}

	switch {
	case broadcaster:
		return ALTStreamer
	case moderator:
		return ALTModerators
	case vip:
		return ALTVIP
	case subscriber:
		return ALTSubscribers
	default:
		return ALTEveryone
	}
}

func cmdCustom(mod *Module, cmd string, data CustomCommand, message helix.EventSubChannelChatMessageEvent) {
	// Check access level
	accessLevel := getUserAccessLevel(message.Badges)

	// Ensure that access level is high enough
	if accessLevels[accessLevel] < accessLevels[data.AccessLevel] {
		return
	}

	var buf bytes.Buffer
	tpl, ok := mod.customTemplates.GetKey(cmd)
	if !ok {
		return
	}
	if err := tpl.Execute(&buf, message); err != nil {
		mod.logger.Error("Failed to execute custom command template", log.Error(err))
		return
	}

	var request WriteMessageRequest

	switch data.ResponseType {
	case ResponseTypeDefault, ResponseTypeChat:
		request = WriteMessageRequest{
			Message: buf.String(),
		}
	case ResponseTypeReply:
		request = WriteMessageRequest{
			Message: buf.String(),
			ReplyTo: message.MessageID,
		}
	case ResponseTypeWhisper:
		request = WriteMessageRequest{
			Message:   buf.String(),
			WhisperTo: message.ChatterUserID,
		}
	case ResponseTypeAnnounce:
		request = WriteMessageRequest{
			Message:  buf.String(),
			Announce: true,
		}
	default:
		mod.logger.Error("Unknown response type", slog.String("type", string(data.ResponseType)))
	}

	WriteMessage(mod.db, mod.logger, request)
}
