package service

import (
	"context"

	roomv1 "hyapp.local/api/proto/room/v1"
	"hyapp/pkg/appcode"
	"hyapp/pkg/roomid"
	"hyapp/pkg/xerr"
	"hyapp/services/room-service/internal/room/state"
)

// GetRoomSnapshot 返回房间页主动同步所需的完整 Room Cell 快照。
// 该查询只读，不刷新 presence、不写 command log，也不隐式 JoinRoom。
func (s *Service) GetRoomSnapshot(ctx context.Context, req *roomv1.GetRoomSnapshotRequest) (*roomv1.GetRoomSnapshotResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode())
	roomID := req.GetRoomId()
	viewerUserID := req.GetViewerUserId()
	if !roomid.ValidStringID(roomID) {
		// 快照查询同样受腾讯 IM GroupID 和 RTC strRoomId 格式约束，避免脏 room_id 进入恢复路径。
		return nil, xerr.New(xerr.InvalidArgument, "room_id is invalid")
	}
	if viewerUserID <= 0 {
		// viewer_user_id 必须来自 gateway 鉴权，room-service 不接受匿名读取完整 presence。
		return nil, xerr.New(xerr.InvalidArgument, "viewer_user_id is required")
	}

	closed, err := s.isRoomClosed(ctx, roomID)
	if err != nil {
		return nil, err
	}
	if closed {
		return nil, xerr.New(xerr.RoomClosed, "room closed")
	}

	snapshot, err := s.currentSnapshot(ctx, roomID)
	if err != nil {
		return nil, err
	}
	if snapshot == nil || snapshot.GetRoomId() == "" {
		return nil, xerr.New(xerr.NotFound, "room not found")
	}
	if snapshot.GetStatus() != state.RoomStatusActive {
		return nil, xerr.New(xerr.RoomClosed, "room closed")
	}
	if snapshotUserBanned(snapshot, viewerUserID, s.clock.Now().UnixMilli()) || findProtoUser(snapshot, viewerUserID) == nil {
		// 完整快照包含在线用户、麦位和房管集合，必须要求 viewer 仍在业务 presence 内。
		return nil, xerr.New(xerr.PermissionDenied, "viewer is not in room")
	}

	followed, err := s.repository.IsRoomFollowed(ctx, viewerUserID, roomID)
	if err != nil {
		return nil, err
	}

	return &roomv1.GetRoomSnapshotResponse{
		Room:         snapshot,
		ServerTimeMs: s.clock.Now().UnixMilli(),
		IsFollowed:   followed,
	}, nil
}
