package service

import (
	"testing"

	"hyapp/services/room-service/internal/room/command"
	"hyapp/services/room-service/internal/room/state"
)

func replayHeartbeat(t *testing.T, current *state.RoomState, userID int64, sentAtMS int64) {
	t.Helper()
	cmd := &command.RoomHeartbeat{Base: command.Base{
		AppCode:   "lalu",
		RequestID: "req-replay-heartbeat",
		CommandID: "cmd-replay-heartbeat",
		ActorID:   userID,
		Room:      current.RoomID,
		SentAtMS:  sentAtMS,
	}}
	if err := replay(current, cmd, sentAtMS); err != nil {
		t.Fatalf("replay heartbeat for user %d failed: %v", userID, err)
	}
}

// 线上心跳会静默恢复丢失的 presence 后才提交命令日志；回放必须重现恢复（含 Version++），
// 否则恢复出的 OnlineUsers/版本与快照谱系分叉。
func TestReplayRoomHeartbeatRecreatesMissingPresence(t *testing.T) {
	ownerID := int64(11)
	adminID := int64(22)
	viewerID := int64(33)
	current := state.NewRoomState("room-replay-heartbeat", ownerID, 4, "voice")
	current.AdminUsers[adminID] = true
	baseVersion := current.Version

	replayHeartbeat(t, current, viewerID, 1_000)
	viewer, exists := current.OnlineUsers[viewerID]
	if !exists || viewer.Role != "audience" || viewer.JoinedAtMS != 1_000 || viewer.LastSeenAtMS != 1_000 {
		t.Fatalf("replayed heal must recreate audience presence from SentAtMS: %+v", viewer)
	}
	if current.Version != baseVersion+1 {
		t.Fatalf("replayed heal must advance version exactly once: base=%d now=%d", baseVersion, current.Version)
	}

	// 角色从权威字段推导：owner/admin 恢复后徽标不丢失。
	replayHeartbeat(t, current, ownerID, 2_000)
	if owner := current.OnlineUsers[ownerID]; owner == nil || owner.Role != "owner" {
		t.Fatalf("replayed heal must restore owner role: %+v", owner)
	}
	replayHeartbeat(t, current, adminID, 3_000)
	if admin := current.OnlineUsers[adminID]; admin == nil || admin.Role != "admin" {
		t.Fatalf("replayed heal must restore admin role: %+v", admin)
	}
}

func TestReplayRoomHeartbeatRefreshesExistingPresence(t *testing.T) {
	viewerID := int64(44)
	current := state.NewRoomState("room-replay-heartbeat-refresh", 11, 4, "voice")
	current.OnlineUsers[viewerID] = &state.RoomUserState{
		UserID:       viewerID,
		Role:         "audience",
		JoinedAtMS:   500,
		LastSeenAtMS: 500,
	}
	baseVersion := current.Version

	replayHeartbeat(t, current, viewerID, 9_000)
	viewer := current.OnlineUsers[viewerID]
	if viewer.LastSeenAtMS != 9_000 || viewer.JoinedAtMS != 500 {
		t.Fatalf("replayed refresh must only update last_seen: %+v", viewer)
	}
	if current.Version != baseVersion+1 {
		t.Fatalf("replayed refresh must advance version exactly once: base=%d now=%d", baseVersion, current.Version)
	}
}
