package roomapi

import (
	"bytes"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"

	roomv1 "hyapp.local/api/proto/room/v1"
)

func TestCreateRoomRejectsMissingRoomAvatar(t *testing.T) {
	handler := New(Config{})
	request := httptest.NewRequest(http.MethodPost, "/api/v1/rooms/create", bytes.NewBufferString(`{
		"command_id": "cmd-create-room",
		"seat_count": 10,
		"mode": "voice",
		"room_name": "No Cover Room"
	}`))
	recorder := httptest.NewRecorder()

	handler.createRoom(recorder, request)

	if recorder.Code != http.StatusBadRequest {
		t.Fatalf("missing room_avatar must fail before upstream calls: status=%d body=%s", recorder.Code, recorder.Body.String())
	}
	if !bytes.Contains(recorder.Body.Bytes(), []byte(`"code":"INVALID_ARGUMENT"`)) {
		t.Fatalf("missing room_avatar must return invalid argument envelope: %s", recorder.Body.String())
	}
}

func TestRoomGiftTabsUsesTypeCodeAsKeyAndTabKeyAsLabel(t *testing.T) {
	tabs := roomGiftTabs(
		[]giftConfigData{
			{GiftTypeCode: "normal"},
			{GiftTypeCode: "lucky"},
			{GiftTypeCode: "disabled"},
		},
		[]giftTypeConfigData{
			{TypeCode: "normal", Name: "普通礼物", TabKey: "Gift", SortOrder: 10},
			{TypeCode: "lucky", Name: "幸运礼物", TabKey: "Lucky", SortOrder: 20},
			{TypeCode: "empty", Name: "空礼物", TabKey: "Empty", SortOrder: 30},
		},
	)

	if len(tabs) != 3 {
		t.Fatalf("tab count mismatch: got %d tabs=%+v", len(tabs), tabs)
	}
	if tabs[1].Key != "normal" || tabs[1].GiftTypeCode != "normal" || tabs[1].Label != "Gift" || tabs[1].Order != 10 {
		t.Fatalf("normal tab mismatch: %+v", tabs[1])
	}
	if tabs[2].Key != "lucky" || tabs[2].GiftTypeCode != "lucky" || tabs[2].Label != "Lucky" || tabs[2].Order != 20 {
		t.Fatalf("lucky tab mismatch: %+v", tabs[2])
	}
}

func TestCreateRoomDataIncludesExplicitIMGroupID(t *testing.T) {
	data := createRoomDataFromProto(&roomv1.CreateRoomResponse{
		Result: &roomv1.CommandResult{Applied: true, RoomVersion: 1, ServerTimeMs: 1700000000000},
		Room: &roomv1.RoomSnapshot{
			RoomId:          "room-create-im",
			OwnerUserId:     1001,
			Mode:            "voice",
			Status:          "active",
			ChatEnabled:     true,
			Version:         1,
			RoomShortId:     "1001",
			OnlineUsers:     []*roomv1.RoomUser{{UserId: 1001, Role: "owner"}},
			RoomExt:         map[string]string{"title": "Create IM", "cover_url": "cover"},
			VisibleRegionId: 10,
		},
	})

	if data.Room.RoomID != "room-create-im" || data.Room.IMGroupID != "room-create-im" {
		t.Fatalf("create response room must expose room_id and im_group_id: %+v", data.Room)
	}
	if data.IM.GroupID != "room-create-im" || !data.IM.NeedJoinGroup {
		t.Fatalf("create response must expose joinable im group: %+v", data.IM)
	}
	if !data.Result.Applied || data.ServerTimeMS != 1700000000000 {
		t.Fatalf("create response result mismatch: %+v", data)
	}
}

func TestRoomSeatDataIncludesGiftValue(t *testing.T) {
	seats := roomSeatDataFromSnapshot(&roomv1.RoomSnapshot{
		RoomId: "room-seat-gift-value",
		MicSeats: []*roomv1.SeatState{{
			SeatNo:    3,
			UserId:    1003,
			GiftValue: 367,
		}},
	})

	if len(seats) != 1 || seats[0].SeatNo != 3 || seats[0].UserID != "1003" || seats[0].GiftValue != 367 {
		t.Fatalf("seat data must expose gift_value: %+v", seats)
	}
}

func TestRoomProfileAgeFromBirth(t *testing.T) {
	now := time.Date(2026, time.May, 27, 12, 0, 0, 0, time.UTC)
	tests := []struct {
		name  string
		birth string
		want  int32
	}{
		{name: "birthday passed", birth: "2000-01-02", want: 26},
		{name: "birthday pending", birth: "2000-12-31", want: 25},
		{name: "today birthday", birth: "2000-05-27", want: 26},
		{name: "invalid", birth: "2000/01/02", want: 0},
		{name: "future", birth: "2030-01-01", want: 0},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			if got := roomProfileAgeFromBirth(test.birth, now); got != test.want {
				t.Fatalf("age mismatch: got %d want %d", got, test.want)
			}
		})
	}
}

func TestRoomProfileCountryFlag(t *testing.T) {
	tests := []struct {
		name    string
		country string
		want    string
	}{
		{name: "upper code", country: "US", want: "🇺🇸"},
		{name: "lower code", country: "sg", want: "🇸🇬"},
		{name: "invalid length", country: "USA", want: ""},
		{name: "invalid character", country: "U1", want: ""},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			if got := roomProfileCountryFlag(test.country); got != test.want {
				t.Fatalf("flag mismatch: got %q want %q", got, test.want)
			}
		})
	}
}
