package main

import (
	"context"
	"fmt"
	"log/slog"
	"os"
	"os/signal"
	"strings"
	"syscall"

	"github.com/disgoorg/disgo"
	"github.com/disgoorg/disgo/bot"
	"github.com/disgoorg/disgo/discord"
	"github.com/disgoorg/disgo/events"
	"github.com/disgoorg/disgo/gateway"
	"github.com/disgoorg/snowflake/v2"
)

type config struct {
	botToken string
	guildID  snowflake.ID
	roleID   snowflake.ID
}

var (
	commands = []discord.ApplicationCommandCreate{
		discord.SlashCommandCreate{
			Name:        "schedule",
			Description: "Collects who is available to a given date",
			Options: []discord.ApplicationCommandOption{
				discord.ApplicationCommandOptionString{
					Name:        "date",
					Description: "When is it scheduled",
					Required:    true,
				},
			},
		},
	}
)

func main() {
	slog.Info("getting config")
	conf := getConfig()
	slog.Info("defining intents")
	client, err := disgo.New(conf.botToken,
		// set gateway options
		bot.WithGatewayConfigOpts(
			// set enabled intents
			gateway.WithIntents(
				gateway.IntentGuilds,
				gateway.IntentGuildMessages,
				//gateway.IntentDirectMessages,
			),
		),
		// add event listeners
		bot.WithEventListenerFunc(commandListener),
		bot.WithEventListenerFunc(interactListener),
	)
	if err != nil {
		panic(err)
	}
	slog.Info("writing Slash commands")
	if _, err = client.Rest().SetGuildCommands(client.ApplicationID(), conf.guildID, commands); err != nil {
		slog.Error("error while registering commands", slog.Any("err", err))
	}

	slog.Info("starting bot")
	// connect to the gateway
	if err = client.OpenGateway(context.TODO()); err != nil {
		panic(err)
	}

	slog.Info("bot startet successfully")
	s := make(chan os.Signal, 1)
	signal.Notify(s, syscall.SIGINT, syscall.SIGTERM)
	<-s
}

func getConfig() config {
	conf := config{}
	conf.botToken = os.Getenv("DISCORD_TOKEN")
	conf.guildID = snowflake.GetEnv("DISCORD_GUILD_ID")
	conf.roleID = snowflake.GetEnv("DISCORD_ROLE_ID")
	return conf
}

func commandListener(event *events.ApplicationCommandInteractionCreate) {
	data := event.SlashCommandInteractionData()
	if data.CommandName() == "schedule" {
		err := event.CreateMessage(
			discord.NewMessageCreateBuilder().
				SetContent(fmt.Sprintf("Will you attend on %s?\nAttending:\n\nNot Attending:\n\n", data.String("date"))).
				AddActionRow(
					discord.ButtonComponent{
						Style:    discord.ButtonStylePrimary,
						Label:    "I will attend",
						CustomID: "attend",
					},
					discord.ButtonComponent{
						Style:    discord.ButtonStyleSecondary,
						Label:    "I will not attend",
						CustomID: "noattend",
					},
				).
				Build(),
		)
		if err != nil {
			slog.Error("error on sending response", slog.Any("err", err))
		}
	}
}

func interactListener(event *events.ComponentInteractionCreate) {
	switch event.ButtonInteractionData().CustomID() {
	case "attend":
		currentcontent := event.Message.Content
		msg := strings.ReplaceAll(currentcontent, event.User().Username+"\n", "")
		msg = strings.ReplaceAll(msg, event.User().Username, "")
		msg = strings.ReplaceAll(msg, "\nAttending:\n", fmt.Sprintf("\nAttending:\n%s\n", event.User().Username))
		event.UpdateMessage(discord.NewMessageUpdateBuilder().
			SetContent(msg).
			Build(),
		)
		return
	case "noattend":
		currentcontent := event.Message.Content
		msg := strings.ReplaceAll(currentcontent, event.User().Username+"\n", "")
		msg = strings.ReplaceAll(msg, event.User().Username, "")
		msg = strings.ReplaceAll(msg, "Not Attending:", fmt.Sprintf("Not Attending:\n%s", event.User().Username))
		event.UpdateMessage(discord.NewMessageUpdateBuilder().
			SetContent(msg).
			Build(),
		)
		return
	}
}
