package rcon

import (
	"encoding/json"
	"fmt"
	"net/url"
	"time"

	"github.com/gorilla/websocket"
)

// RconRequest is the JSON payload sent to Rust's WebRCON.
type RconRequest struct {
	Identifier int    `json:"Identifier"`
	Message    string `json:"Message"`
	Name       string `json:"Name"`
}

// RconResponse is the JSON payload received from Rust's WebRCON.
type RconResponse struct {
	Identifier int    `json:"Identifier"`
	Message    string `json:"Message"`
	Type       string `json:"Type"`
}

// SendCommand opens a WebSocket to the Rust server's RCON port, sends
// a single command, reads the response, and closes the connection.
func SendCommand(port int, password string, command string) (string, error) {
	u := url.URL{
		Scheme: "ws",
		Host:   fmt.Sprintf("127.0.0.1:%d", port),
		Path:   fmt.Sprintf("/%s", password),
	}

	dialer := websocket.Dialer{
		HandshakeTimeout: 5 * time.Second,
	}

	conn, _, err := dialer.Dial(u.String(), nil)
	if err != nil {
		return "", fmt.Errorf("rcon dial failed: %w", err)
	}
	defer conn.Close()

	// Set read deadline
	conn.SetReadDeadline(time.Now().Add(10 * time.Second))

	req := RconRequest{
		Identifier: 1,
		Message:    command,
		Name:       "Corrosion",
	}

	data, err := json.Marshal(req)
	if err != nil {
		return "", fmt.Errorf("rcon marshal failed: %w", err)
	}

	if err := conn.WriteMessage(websocket.TextMessage, data); err != nil {
		return "", fmt.Errorf("rcon write failed: %w", err)
	}

	// Read response — may get multiple messages (Generic, Warning, etc.)
	// We want the first response with our Identifier.
	for {
		_, message, err := conn.ReadMessage()
		if err != nil {
			return "", fmt.Errorf("rcon read failed: %w", err)
		}

		var resp RconResponse
		if err := json.Unmarshal(message, &resp); err != nil {
			continue // skip unparseable messages
		}

		if resp.Identifier == req.Identifier {
			return resp.Message, nil
		}
	}
}
