package roommq

import (
	"strings"
	"testing"

	"google.golang.org/protobuf/proto"
	roomeventsv1 "hyapp.local/api/proto/events/room/v1"
)

func TestRoomOutboxMessageRoundTrip(t *testing.T) {
	body, err := proto.Marshal(&roomeventsv1.RoomRocketIgnited{RocketId: "rocket-1", Level: 2, LaunchAtMs: 12345})
	if err != nil {
		t.Fatalf("marshal body: %v", err)
	}
	envelope := &roomeventsv1.EventEnvelope{
		AppCode:      "default",
		EventId:      "evt-1",
		EventType:    "RoomRocketIgnited",
		RoomId:       "room-1",
		RoomVersion:  9,
		OccurredAtMs: 12300,
		Body:         body,
	}
	encoded, err := EncodeRoomOutboxMessage(envelope)
	if err != nil {
		t.Fatalf("encode: %v", err)
	}
	decoded, message, err := DecodeRoomOutboxMessage(encoded)
	if err != nil {
		t.Fatalf("decode: %v", err)
	}
	if message.MessageType != MessageTypeRoomOutboxEvent || decoded.GetEventId() != envelope.GetEventId() {
		t.Fatalf("unexpected decoded message: %#v %#v", message, decoded)
	}
}

func TestRoomEventTypeTagUsesExactTrimmedEventType(t *testing.T) {
	tag, err := EventTypeTag("  RoomGiftSent  ")
	if err != nil {
		t.Fatalf("EventTypeTag failed: %v", err)
	}
	if tag != EventTypeRoomGiftSent {
		t.Fatalf("event tag = %q, want %q", tag, EventTypeRoomGiftSent)
	}

	for _, invalid := range []string{"", TagRoomOutboxEvent, "Room GiftSent", "RoomGiftSent || *", "Room.GiftSent"} {
		if _, err := EventTypeTag(invalid); err == nil {
			t.Fatalf("EventTypeTag(%q) unexpectedly succeeded", invalid)
		}
	}
}

func TestRoomLegacyCompatibleTagExpressionIsDeterministicAndDeduplicated(t *testing.T) {
	first, err := LegacyCompatibleTagExpression(
		EventTypeRoomUserJoined,
		EventTypeRoomGiftSent,
		EventTypeRoomUserJoined,
	)
	if err != nil {
		t.Fatalf("LegacyCompatibleTagExpression failed: %v", err)
	}
	second, err := LegacyCompatibleTagExpression(EventTypeRoomGiftSent, EventTypeRoomUserJoined)
	if err != nil {
		t.Fatalf("LegacyCompatibleTagExpression failed: %v", err)
	}
	if first != second {
		t.Fatalf("expressions differ by input order: first=%q second=%q", first, second)
	}
	want := TagRoomOutboxEvent + " || " + EventTypeRoomGiftSent + " || " + EventTypeRoomUserJoined
	if first != want {
		t.Fatalf("expression = %q, want %q", first, want)
	}
	if strings.Count(first, EventTypeRoomUserJoined) != 1 {
		t.Fatalf("typed tag was not deduplicated: %q", first)
	}
}

func TestRoomLegacyCompatibleTagExpressionRejectsUnsafeOrMissingTypedTags(t *testing.T) {
	for _, eventTypes := range [][]string{
		nil,
		{TagRoomOutboxEvent},
		{"RoomGiftSent || *"},
	} {
		if _, err := LegacyCompatibleTagExpression(eventTypes...); err == nil {
			t.Fatalf("LegacyCompatibleTagExpression(%v) unexpectedly succeeded", eventTypes)
		}
	}
}

func TestRoomRocketLaunchDueRoundTrip(t *testing.T) {
	encoded, err := EncodeRoomRocketLaunchDueMessage(RoomRocketLaunchDueMessage{
		AppCode:    "default",
		RoomID:     "room-1",
		RocketID:   "rocket-1",
		Level:      1,
		LaunchAtMS: 12345,
		ResetAtMS:  99999,
		CommandID:  "cmd_room_rocket_launch_rocket-1",
	})
	if err != nil {
		t.Fatalf("encode: %v", err)
	}
	decoded, err := DecodeRoomRocketLaunchDueMessage(encoded)
	if err != nil {
		t.Fatalf("decode: %v", err)
	}
	if decoded.MessageType != MessageTypeRoomRocketLaunchDue || decoded.RocketID != "rocket-1" || decoded.LaunchAtMS != 12345 {
		t.Fatalf("unexpected decoded message: %#v", decoded)
	}
}
