package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/url"
	"os"
	"strings"

	"github.com/gorilla/websocket"
)

type Event struct {
	Type    string          `json:"type"`
	Payload json.RawMessage `json:"payload"`
}

type Message struct {
	ID        string `json:"id"`
	ChannelID string `json:"channel_id"`
	AuthorID  string `json:"author_id"`
	Username  string `json:"username"`
	Content   string `json:"content"`
}

var bannedWords = []string{
	"spam",
	"scam",
	"phishing",
}

func main() {
	token := os.Getenv("BOT_TOKEN")
	if token == "" {
		log.Fatal("BOT_TOKEN environment variable required")
	}

	host := os.Getenv("DUMPSTER_HOST")
	if host == "" {
		host = "localhost:8080"
	}

	u := url.URL{
		Scheme:   "ws",
		Host:     host,
		Path:     "/ws/bot",
		RawQuery: "token=" + token,
	}

	log.Printf("Connecting to %s", u.String())

	c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
	if err != nil {
		log.Fatal("dial:", err)
	}
	defer c.Close()

	log.Println("Modbot connected!")

	for {
		_, message, err := c.ReadMessage()
		if err != nil {
			log.Println("read:", err)
			break
		}

		var event Event
		if err := json.Unmarshal(message, &event); err != nil {
			continue
		}

		switch event.Type {
		case "MESSAGE_CREATE":
			var msg Message
			if err := json.Unmarshal(event.Payload, &msg); err != nil {
				continue
			}
			handleMessage(c, msg)
		}
	}
}

func handleMessage(c *websocket.Conn, msg Message) {
	content := strings.ToLower(msg.Content)

	// Check for banned words
	for _, word := range bannedWords {
		if strings.Contains(content, word) {
			log.Printf("Deleting message from %s: contains banned word '%s'", msg.Username, word)
			// Delete the message
			deleteMsg := map[string]interface{}{
				"type": "DELETE_MESSAGE",
				"payload": map[string]string{
					"channel_id": msg.ChannelID,
					"message_id": msg.ID,
				},
			}
			data, _ := json.Marshal(deleteMsg)
			c.WriteMessage(websocket.TextMessage, data)

			// Send warning
			sendMessage(c, msg.ChannelID, fmt.Sprintf(
				"⚠️ <@%s>, your message was removed (contained banned content).",
				msg.AuthorID,
			))
			return
		}
	}

	// Handle slash commands
	if strings.HasPrefix(msg.Content, "/kick") {
		handleKick(c, msg)
	} else if strings.HasPrefix(msg.Content, "/ban") {
		handleBan(c, msg)
	} else if strings.HasPrefix(msg.Content, "/purge") {
		handlePurge(c, msg)
	}
}

func handleKick(c *websocket.Conn, msg Message) {
	parts := strings.Fields(msg.Content)
	if len(parts) < 2 {
		sendMessage(c, msg.ChannelID, "Usage: /kick @user [reason]")
		return
	}
	// Extract user ID from mention format <@user_id>
	targetID := strings.TrimPrefix(parts[0], "<@")
	targetID = strings.TrimSuffix(targetID, ">")

	reason := "No reason provided"
	if len(parts) > 2 {
		reason = strings.Join(parts[2:], " ")
	}

	log.Printf("Kick request: %s -> %s (%s)", msg.Username, targetID, reason)
	sendMessage(c, msg.ChannelID, fmt.Sprintf(
		"👢 <@%s> has been kicked. Reason: %s",
		targetID, reason,
	))
}

func handleBan(c *websocket.Conn, msg Message) {
	parts := strings.Fields(msg.Content)
	if len(parts) < 2 {
		sendMessage(c, msg.ChannelID, "Usage: /ban @user [reason]")
		return
	}
	targetID := strings.TrimPrefix(parts[0], "<@")
	targetID = strings.TrimSuffix(targetID, ">")

	reason := "No reason provided"
	if len(parts) > 2 {
		reason = strings.Join(parts[2:], " ")
	}

	log.Printf("Ban request: %s -> %s (%s)", msg.Username, targetID, reason)
	sendMessage(c, msg.ChannelID, fmt.Sprintf(
		"🔨 <@%s> has been banned. Reason: %s",
		targetID, reason,
	))
}

func handlePurge(c *websocket.Conn, msg Message) {
	parts := strings.Fields(msg.Content)
	if len(parts) < 2 {
		sendMessage(c, msg.ChannelID, "Usage: /purge <number>")
		return
	}

	count := 10 // default
	fmt.Sscanf(parts[1], "%d", &count)
	if count > 100 {
		count = 100
	}

	log.Printf("Purge request: %s -> %d messages", msg.Username, count)
	sendMessage(c, msg.ChannelID, fmt.Sprintf(
		"🧹 Purging %d messages...",
		count,
	))
}

func sendMessage(c *websocket.Conn, channelID, content string) {
	msg := map[string]interface{}{
		"type": "SEND_MESSAGE",
		"payload": map[string]string{
			"channel_id": channelID,
			"content":    content,
		},
	}
	data, _ := json.Marshal(msg)
	c.WriteMessage(websocket.TextMessage, data)
}
