package gamemanagement

import (
	"testing"

	gamev1 "hyapp.local/api/proto/game/v1"
)

func TestPlatformFromProtoReturnsCallbackSecret(t *testing.T) {
	const secret = "yomi-or-lingxian-secret"

	got := platformFromProto(&gamev1.GamePlatform{
		PlatformCode:      "yomi",
		CallbackSecret:    secret,
		CallbackSecretSet: true,
	})

	if got.CallbackSecret != secret {
		t.Fatalf("CallbackSecret = %q, want %q", got.CallbackSecret, secret)
	}
	if !got.CallbackSecretSet {
		t.Fatal("CallbackSecretSet = false, want true")
	}
}

func TestSelfGameNewUserPolicyKeepsNormalPhaseTargetWinRate(t *testing.T) {
	proto := (selfGameNewUserPolicyRequest{
		Enabled:                         true,
		ProtectionRounds:                30,
		ProtectionHours:                 168,
		MaxStakeCoin:                    5000,
		LifetimeSubsidyQuotaCoin:        30000,
		Day1SubsidyQuotaCoin:            15000,
		SingleRoundSubsidyCapCoin:       5000,
		StrategyLevel:                   "soft_boost",
		LoseStreakProtectionEnabled:     true,
		LoseStreakTrigger:               2,
		NormalPhaseTargetWinRatePercent: 57,
		BlackPoolRobotForceWinEnabled:   true,
	}).toProto("dice")

	if proto.GetNormalPhaseTargetWinRatePercent() != 57 {
		t.Fatalf("request normal phase target = %d, want 57", proto.GetNormalPhaseTargetWinRatePercent())
	}
	if !proto.GetBlackPoolRobotForceWinEnabled() {
		t.Fatal("request black pool robot force win switch was not preserved")
	}

	dto := selfGameNewUserPolicyFromProto(&gamev1.SelfGameNewUserPolicy{
		GameId:                          "dice",
		NormalPhaseTargetWinRatePercent: 57,
		BlackPoolRobotForceWinEnabled:   true,
	})
	if dto.NormalPhaseTargetWinRatePercent != 57 {
		t.Fatalf("dto normal phase target = %d, want 57", dto.NormalPhaseTargetWinRatePercent)
	}
	if !dto.BlackPoolRobotForceWinEnabled {
		t.Fatal("dto black pool robot force win switch was not preserved")
	}
}

func TestRoomRPSConfigRequestRequiresFourGiftTiers(t *testing.T) {
	_, err := (roomRPSConfigRequest{
		Status:             "active",
		ChallengeTimeoutMS: 600000,
		RevealCountdownMS:  3000,
		StakeGifts: []roomRPSStakeGiftReq{
			{GiftID: "1001", Enabled: true, SortOrder: 1},
			{GiftID: "1002", Enabled: true, SortOrder: 2},
			{GiftID: "1003", Enabled: true, SortOrder: 3},
		},
	}).toProto()

	if err == nil {
		t.Fatal("toProto must reject room rps config without exactly four gift tiers")
	}
}

func TestRoomRPSConfigRequestDefaultsOpenConfig(t *testing.T) {
	got, err := (roomRPSConfigRequest{
		StakeGifts: []roomRPSStakeGiftReq{
			{GiftID: "1001", Enabled: true},
			{GiftID: "1002", Enabled: true},
			{GiftID: "1003", Enabled: true},
			{GiftID: "1004", Enabled: true},
		},
	}).toProto()
	if err != nil {
		t.Fatalf("toProto failed: %v", err)
	}
	if got.GetStatus() != "active" || got.GetChallengeTimeoutMs() != 600000 || got.GetRevealCountdownMs() != 3000 {
		t.Fatalf("room rps default config mismatch: %+v", got)
	}
	if got.GetStakeGifts()[0].GetSortOrder() != 4 || got.GetStakeGifts()[3].GetSortOrder() != 1 {
		t.Fatalf("default sort order mismatch: %+v", got.GetStakeGifts())
	}
}

func TestRoomRPSConfigRequestAcceptsStringGiftIDs(t *testing.T) {
	got, err := (roomRPSConfigRequest{
		StakeGifts: []roomRPSStakeGiftReq{
			{GiftID: "Gifi-3", Enabled: true, SortOrder: 1},
			{GiftID: "Gifi-2", Enabled: true, SortOrder: 2},
			{GiftID: "Gifi-1", Enabled: true, SortOrder: 3},
			{GiftID: "lw1", Enabled: true, SortOrder: 4},
		},
	}).toProto()
	if err != nil {
		t.Fatalf("toProto should accept string gift ids: %v", err)
	}
	if got.GetStakeGifts()[0].GetGiftIdText() != "Gifi-3" || got.GetStakeGifts()[0].GetGiftId() != 0 {
		t.Fatalf("string gift id should stay in text field without fake numeric id: %+v", got.GetStakeGifts()[0])
	}
}

func TestRoomRPSConfigFromProtoIncludesGiftAnimationURL(t *testing.T) {
	got := roomRPSConfigFromProto(&gamev1.RoomRPSConfig{
		AppCode: "lalu",
		GameId:  "room_rps",
		Status:  "active",
		StakeGifts: []*gamev1.RoomRPSStakeGift{
			{
				GiftIdText:       "87",
				GiftName:         "彩蛋兔",
				GiftIconUrl:      "https://cdn.example.test/gifts/egg-rabbit.png",
				GiftAnimationUrl: "https://cdn.example.test/gifts/egg-rabbit.mp4",
				GiftPriceCoin:    40000,
				Enabled:          true,
				SortOrder:        1,
			},
		},
	})

	if len(got.StakeGifts) != 1 {
		t.Fatalf("expected one stake gift, got %+v", got.StakeGifts)
	}
	if got.StakeGifts[0].GiftIconURL != "https://cdn.example.test/gifts/egg-rabbit.png" || got.StakeGifts[0].GiftAnimationURL != "https://cdn.example.test/gifts/egg-rabbit.mp4" {
		t.Fatalf("room rps admin gift media fields mismatch: %+v", got.StakeGifts[0])
	}
}

func TestRoomRPSChallengeFromProtoKeepsLargeIDsAsStrings(t *testing.T) {
	got := roomRPSChallengeFromProto(&gamev1.RoomRPSChallenge{
		ChallengeId:  "rps-1",
		StakeGiftId:  9007199254740993,
		Initiator:    &gamev1.RoomRPSPlayer{UserId: 9007199254740995, Gesture: "rock"},
		WinnerUserId: 9007199254740995,
	})

	if got.StakeGiftID != "9007199254740993" || got.Initiator.UserID != "9007199254740995" || got.WinnerUserID != "9007199254740995" {
		t.Fatalf("large IDs must stay string-safe in admin JSON: %+v", got)
	}
}
