package client

import (
	"context"

	"google.golang.org/grpc"
	roomv1 "hyapp.local/api/proto/room/v1"
)

// RoomClient 抽象 gateway 对 room-service 的 gRPC 编排依赖。
type RoomClient interface {
	CreateRoom(ctx context.Context, req *roomv1.CreateRoomRequest) (*roomv1.CreateRoomResponse, error)
	UpdateRoomProfile(ctx context.Context, req *roomv1.UpdateRoomProfileRequest) (*roomv1.UpdateRoomProfileResponse, error)
	SaveRoomBackground(ctx context.Context, req *roomv1.SaveRoomBackgroundRequest) (*roomv1.SaveRoomBackgroundResponse, error)
	SetRoomBackground(ctx context.Context, req *roomv1.SetRoomBackgroundRequest) (*roomv1.SetRoomBackgroundResponse, error)
	JoinRoom(ctx context.Context, req *roomv1.JoinRoomRequest) (*roomv1.JoinRoomResponse, error)
	RoomHeartbeat(ctx context.Context, req *roomv1.RoomHeartbeatRequest) (*roomv1.RoomHeartbeatResponse, error)
	LeaveRoom(ctx context.Context, req *roomv1.LeaveRoomRequest) (*roomv1.LeaveRoomResponse, error)
	MicUp(ctx context.Context, req *roomv1.MicUpRequest) (*roomv1.MicUpResponse, error)
	MicDown(ctx context.Context, req *roomv1.MicDownRequest) (*roomv1.MicDownResponse, error)
	ChangeMicSeat(ctx context.Context, req *roomv1.ChangeMicSeatRequest) (*roomv1.ChangeMicSeatResponse, error)
	ConfirmMicPublishing(ctx context.Context, req *roomv1.ConfirmMicPublishingRequest) (*roomv1.ConfirmMicPublishingResponse, error)
	MicHeartbeat(ctx context.Context, req *roomv1.MicHeartbeatRequest) (*roomv1.MicHeartbeatResponse, error)
	SetMicMute(ctx context.Context, req *roomv1.SetMicMuteRequest) (*roomv1.SetMicMuteResponse, error)
	ApplyRTCEvent(ctx context.Context, req *roomv1.ApplyRTCEventRequest) (*roomv1.ApplyRTCEventResponse, error)
	SetMicSeatLock(ctx context.Context, req *roomv1.SetMicSeatLockRequest) (*roomv1.SetMicSeatLockResponse, error)
	SetChatEnabled(ctx context.Context, req *roomv1.SetChatEnabledRequest) (*roomv1.SetChatEnabledResponse, error)
	SetRoomPassword(ctx context.Context, req *roomv1.SetRoomPasswordRequest) (*roomv1.SetRoomPasswordResponse, error)
	SetRoomAdmin(ctx context.Context, req *roomv1.SetRoomAdminRequest) (*roomv1.SetRoomAdminResponse, error)
	MuteUser(ctx context.Context, req *roomv1.MuteUserRequest) (*roomv1.MuteUserResponse, error)
	KickUser(ctx context.Context, req *roomv1.KickUserRequest) (*roomv1.KickUserResponse, error)
	UnbanUser(ctx context.Context, req *roomv1.UnbanUserRequest) (*roomv1.UnbanUserResponse, error)
	SendGift(ctx context.Context, req *roomv1.SendGiftRequest) (*roomv1.SendGiftResponse, error)
	FollowRoom(ctx context.Context, req *roomv1.FollowRoomRequest) (*roomv1.FollowRoomResponse, error)
	UnfollowRoom(ctx context.Context, req *roomv1.UnfollowRoomRequest) (*roomv1.UnfollowRoomResponse, error)
}

// RoomGuardClient 抽象 gateway 对 room-service 实时守卫 RPC 的依赖。
// RoomGuardClient 暴露房间权威状态查询；腾讯 IM 发消息不再同步调用该接口，避免把共享 SDKAppID 的发送链路串到 gateway。
type RoomGuardClient interface {
	CheckSpeakPermission(ctx context.Context, req *roomv1.CheckSpeakPermissionRequest) (*roomv1.CheckSpeakPermissionResponse, error)
	VerifyRoomPresence(ctx context.Context, req *roomv1.VerifyRoomPresenceRequest) (*roomv1.VerifyRoomPresenceResponse, error)
	ResolveRoomAppCode(ctx context.Context, req *roomv1.ResolveRoomAppCodeRequest) (*roomv1.ResolveRoomAppCodeResponse, error)
}

// RoomVIPFeatureClient 是新版房间 VIP 展示能力的窄接口，避免扩大旧 RoomClient fake。
type RoomVIPFeatureClient interface {
	ApplyRoomDecoration(ctx context.Context, req *roomv1.ApplyRoomDecorationRequest) (*roomv1.ApplyRoomDecorationResponse, error)
	SendRoomImage(ctx context.Context, req *roomv1.SendRoomImageRequest) (*roomv1.SendRoomImageResponse, error)
}

// RoomMediaGuardClient 在 COS 写入前向 room owner 校验上传权限。
type RoomMediaGuardClient interface {
	AuthorizeRoomMediaUpload(ctx context.Context, req *roomv1.AuthorizeRoomMediaUploadRequest) (*roomv1.AuthorizeRoomMediaUploadResponse, error)
	CompleteRoomMediaUpload(ctx context.Context, req *roomv1.CompleteRoomMediaUploadRequest) (*roomv1.CompleteRoomMediaUploadResponse, error)
}

// RoomQueryClient 抽象 gateway 对 room-service 读模型查询的依赖。
type RoomQueryClient interface {
	ListRooms(ctx context.Context, req *roomv1.ListRoomsRequest) (*roomv1.ListRoomsResponse, error)
	ListRoomsByOwners(ctx context.Context, req *roomv1.ListRoomsByOwnersRequest) (*roomv1.ListRoomsResponse, error)
	ListRoomFeeds(ctx context.Context, req *roomv1.ListRoomFeedsRequest) (*roomv1.ListRoomsResponse, error)
	ListRoomGiftLeaderboard(ctx context.Context, req *roomv1.ListRoomGiftLeaderboardRequest) (*roomv1.ListRoomGiftLeaderboardResponse, error)
	ListRoomContributionRank(ctx context.Context, req *roomv1.ListRoomContributionRankRequest) (*roomv1.ListRoomContributionRankResponse, error)
	GetMyRoom(ctx context.Context, req *roomv1.GetMyRoomRequest) (*roomv1.GetMyRoomResponse, error)
	GetCurrentRoom(ctx context.Context, req *roomv1.GetCurrentRoomRequest) (*roomv1.GetCurrentRoomResponse, error)
	GetRoomSnapshot(ctx context.Context, req *roomv1.GetRoomSnapshotRequest) (*roomv1.GetRoomSnapshotResponse, error)
	ListRoomBackgrounds(ctx context.Context, req *roomv1.ListRoomBackgroundsRequest) (*roomv1.ListRoomBackgroundsResponse, error)
	GetRoomRocket(ctx context.Context, req *roomv1.GetRoomRocketRequest) (*roomv1.GetRoomRocketResponse, error)
	ListRoomOnlineUsers(ctx context.Context, req *roomv1.ListRoomOnlineUsersRequest) (*roomv1.ListRoomOnlineUsersResponse, error)
	ListRoomBannedUsers(ctx context.Context, req *roomv1.ListRoomBannedUsersRequest) (*roomv1.ListRoomBannedUsersResponse, error)
}

type grpcRoomClient struct {
	client roomv1.RoomCommandServiceClient
}

type grpcRoomGuardClient struct {
	client roomv1.RoomGuardServiceClient
}

type grpcRoomQueryClient struct {
	client roomv1.RoomQueryServiceClient
}

// NewGRPCRoomClient 用 gRPC 连接构造 room-service client。
func NewGRPCRoomClient(conn *grpc.ClientConn) RoomClient {
	return &grpcRoomClient{
		client: roomv1.NewRoomCommandServiceClient(conn),
	}
}

// NewGRPCRoomGuardClient 用同一条 room-service gRPC 连接构造守卫 client。
func NewGRPCRoomGuardClient(conn *grpc.ClientConn) RoomGuardClient {
	return &grpcRoomGuardClient{
		client: roomv1.NewRoomGuardServiceClient(conn),
	}
}

// NewGRPCRoomQueryClient 用同一条 room-service gRPC 连接构造查询 client。
func NewGRPCRoomQueryClient(conn *grpc.ClientConn) RoomQueryClient {
	return &grpcRoomQueryClient{
		client: roomv1.NewRoomQueryServiceClient(conn),
	}
}

func (c *grpcRoomClient) CreateRoom(ctx context.Context, req *roomv1.CreateRoomRequest) (*roomv1.CreateRoomResponse, error) {
	return c.client.CreateRoom(ctx, req)
}

func (c *grpcRoomClient) UpdateRoomProfile(ctx context.Context, req *roomv1.UpdateRoomProfileRequest) (*roomv1.UpdateRoomProfileResponse, error) {
	return c.client.UpdateRoomProfile(ctx, req)
}

func (c *grpcRoomClient) SaveRoomBackground(ctx context.Context, req *roomv1.SaveRoomBackgroundRequest) (*roomv1.SaveRoomBackgroundResponse, error) {
	return c.client.SaveRoomBackground(ctx, req)
}

func (c *grpcRoomClient) SetRoomBackground(ctx context.Context, req *roomv1.SetRoomBackgroundRequest) (*roomv1.SetRoomBackgroundResponse, error) {
	return c.client.SetRoomBackground(ctx, req)
}

func (c *grpcRoomClient) ApplyRoomDecoration(ctx context.Context, req *roomv1.ApplyRoomDecorationRequest) (*roomv1.ApplyRoomDecorationResponse, error) {
	return c.client.ApplyRoomDecoration(ctx, req)
}

func (c *grpcRoomClient) SendRoomImage(ctx context.Context, req *roomv1.SendRoomImageRequest) (*roomv1.SendRoomImageResponse, error) {
	return c.client.SendRoomImage(ctx, req)
}

func (c *grpcRoomClient) JoinRoom(ctx context.Context, req *roomv1.JoinRoomRequest) (*roomv1.JoinRoomResponse, error) {
	return c.client.JoinRoom(ctx, req)
}

func (c *grpcRoomClient) RoomHeartbeat(ctx context.Context, req *roomv1.RoomHeartbeatRequest) (*roomv1.RoomHeartbeatResponse, error) {
	return c.client.RoomHeartbeat(ctx, req)
}

func (c *grpcRoomClient) LeaveRoom(ctx context.Context, req *roomv1.LeaveRoomRequest) (*roomv1.LeaveRoomResponse, error) {
	return c.client.LeaveRoom(ctx, req)
}

func (c *grpcRoomClient) MicUp(ctx context.Context, req *roomv1.MicUpRequest) (*roomv1.MicUpResponse, error) {
	return c.client.MicUp(ctx, req)
}

func (c *grpcRoomClient) MicDown(ctx context.Context, req *roomv1.MicDownRequest) (*roomv1.MicDownResponse, error) {
	return c.client.MicDown(ctx, req)
}

func (c *grpcRoomClient) ChangeMicSeat(ctx context.Context, req *roomv1.ChangeMicSeatRequest) (*roomv1.ChangeMicSeatResponse, error) {
	return c.client.ChangeMicSeat(ctx, req)
}

func (c *grpcRoomClient) ConfirmMicPublishing(ctx context.Context, req *roomv1.ConfirmMicPublishingRequest) (*roomv1.ConfirmMicPublishingResponse, error) {
	return c.client.ConfirmMicPublishing(ctx, req)
}

func (c *grpcRoomClient) MicHeartbeat(ctx context.Context, req *roomv1.MicHeartbeatRequest) (*roomv1.MicHeartbeatResponse, error) {
	return c.client.MicHeartbeat(ctx, req)
}

func (c *grpcRoomClient) SetMicMute(ctx context.Context, req *roomv1.SetMicMuteRequest) (*roomv1.SetMicMuteResponse, error) {
	return c.client.SetMicMute(ctx, req)
}

func (c *grpcRoomClient) ApplyRTCEvent(ctx context.Context, req *roomv1.ApplyRTCEventRequest) (*roomv1.ApplyRTCEventResponse, error) {
	return c.client.ApplyRTCEvent(ctx, req)
}

func (c *grpcRoomClient) SetMicSeatLock(ctx context.Context, req *roomv1.SetMicSeatLockRequest) (*roomv1.SetMicSeatLockResponse, error) {
	return c.client.SetMicSeatLock(ctx, req)
}

func (c *grpcRoomClient) SetChatEnabled(ctx context.Context, req *roomv1.SetChatEnabledRequest) (*roomv1.SetChatEnabledResponse, error) {
	return c.client.SetChatEnabled(ctx, req)
}

func (c *grpcRoomClient) SetRoomPassword(ctx context.Context, req *roomv1.SetRoomPasswordRequest) (*roomv1.SetRoomPasswordResponse, error) {
	return c.client.SetRoomPassword(ctx, req)
}

func (c *grpcRoomClient) SetRoomAdmin(ctx context.Context, req *roomv1.SetRoomAdminRequest) (*roomv1.SetRoomAdminResponse, error) {
	return c.client.SetRoomAdmin(ctx, req)
}

func (c *grpcRoomClient) MuteUser(ctx context.Context, req *roomv1.MuteUserRequest) (*roomv1.MuteUserResponse, error) {
	return c.client.MuteUser(ctx, req)
}

func (c *grpcRoomClient) KickUser(ctx context.Context, req *roomv1.KickUserRequest) (*roomv1.KickUserResponse, error) {
	return c.client.KickUser(ctx, req)
}

func (c *grpcRoomClient) UnbanUser(ctx context.Context, req *roomv1.UnbanUserRequest) (*roomv1.UnbanUserResponse, error) {
	return c.client.UnbanUser(ctx, req)
}

func (c *grpcRoomClient) SendGift(ctx context.Context, req *roomv1.SendGiftRequest) (*roomv1.SendGiftResponse, error) {
	return c.client.SendGift(ctx, req)
}

func (c *grpcRoomClient) FollowRoom(ctx context.Context, req *roomv1.FollowRoomRequest) (*roomv1.FollowRoomResponse, error) {
	return c.client.FollowRoom(ctx, req)
}

func (c *grpcRoomClient) UnfollowRoom(ctx context.Context, req *roomv1.UnfollowRoomRequest) (*roomv1.UnfollowRoomResponse, error) {
	return c.client.UnfollowRoom(ctx, req)
}

func (c *grpcRoomGuardClient) CheckSpeakPermission(ctx context.Context, req *roomv1.CheckSpeakPermissionRequest) (*roomv1.CheckSpeakPermissionResponse, error) {
	return c.client.CheckSpeakPermission(ctx, req)
}

func (c *grpcRoomGuardClient) VerifyRoomPresence(ctx context.Context, req *roomv1.VerifyRoomPresenceRequest) (*roomv1.VerifyRoomPresenceResponse, error) {
	return c.client.VerifyRoomPresence(ctx, req)
}

func (c *grpcRoomGuardClient) ResolveRoomAppCode(ctx context.Context, req *roomv1.ResolveRoomAppCodeRequest) (*roomv1.ResolveRoomAppCodeResponse, error) {
	return c.client.ResolveRoomAppCode(ctx, req)
}

func (c *grpcRoomGuardClient) AuthorizeRoomMediaUpload(ctx context.Context, req *roomv1.AuthorizeRoomMediaUploadRequest) (*roomv1.AuthorizeRoomMediaUploadResponse, error) {
	return c.client.AuthorizeRoomMediaUpload(ctx, req)
}

func (c *grpcRoomGuardClient) CompleteRoomMediaUpload(ctx context.Context, req *roomv1.CompleteRoomMediaUploadRequest) (*roomv1.CompleteRoomMediaUploadResponse, error) {
	return c.client.CompleteRoomMediaUpload(ctx, req)
}

func (c *grpcRoomQueryClient) ListRooms(ctx context.Context, req *roomv1.ListRoomsRequest) (*roomv1.ListRoomsResponse, error) {
	return c.client.ListRooms(ctx, req)
}

func (c *grpcRoomQueryClient) ListRoomsByOwners(ctx context.Context, req *roomv1.ListRoomsByOwnersRequest) (*roomv1.ListRoomsResponse, error) {
	return c.client.ListRoomsByOwners(ctx, req)
}

func (c *grpcRoomQueryClient) ListRoomFeeds(ctx context.Context, req *roomv1.ListRoomFeedsRequest) (*roomv1.ListRoomsResponse, error) {
	return c.client.ListRoomFeeds(ctx, req)
}

func (c *grpcRoomQueryClient) ListRoomGiftLeaderboard(ctx context.Context, req *roomv1.ListRoomGiftLeaderboardRequest) (*roomv1.ListRoomGiftLeaderboardResponse, error) {
	return c.client.ListRoomGiftLeaderboard(ctx, req)
}

func (c *grpcRoomQueryClient) ListRoomContributionRank(ctx context.Context, req *roomv1.ListRoomContributionRankRequest) (*roomv1.ListRoomContributionRankResponse, error) {
	return c.client.ListRoomContributionRank(ctx, req)
}

func (c *grpcRoomQueryClient) GetMyRoom(ctx context.Context, req *roomv1.GetMyRoomRequest) (*roomv1.GetMyRoomResponse, error) {
	return c.client.GetMyRoom(ctx, req)
}

func (c *grpcRoomQueryClient) GetCurrentRoom(ctx context.Context, req *roomv1.GetCurrentRoomRequest) (*roomv1.GetCurrentRoomResponse, error) {
	return c.client.GetCurrentRoom(ctx, req)
}

// BatchGetUserVoiceRoomPresences 保持为具体 client 能力；只有个人资料页入口依赖它，避免扩大所有房间查询 mock 的接口面。
func (c *grpcRoomQueryClient) BatchGetUserVoiceRoomPresences(ctx context.Context, req *roomv1.BatchGetUserVoiceRoomPresencesRequest) (*roomv1.BatchGetUserVoiceRoomPresencesResponse, error) {
	return c.client.BatchGetUserVoiceRoomPresences(ctx, req)
}

func (c *grpcRoomQueryClient) GetRoomSnapshot(ctx context.Context, req *roomv1.GetRoomSnapshotRequest) (*roomv1.GetRoomSnapshotResponse, error) {
	return c.client.GetRoomSnapshot(ctx, req)
}

func (c *grpcRoomQueryClient) ListRoomBackgrounds(ctx context.Context, req *roomv1.ListRoomBackgroundsRequest) (*roomv1.ListRoomBackgroundsResponse, error) {
	return c.client.ListRoomBackgrounds(ctx, req)
}

func (c *grpcRoomQueryClient) GetRoomRocket(ctx context.Context, req *roomv1.GetRoomRocketRequest) (*roomv1.GetRoomRocketResponse, error) {
	return c.client.GetRoomRocket(ctx, req)
}

func (c *grpcRoomQueryClient) ListRoomOnlineUsers(ctx context.Context, req *roomv1.ListRoomOnlineUsersRequest) (*roomv1.ListRoomOnlineUsersResponse, error) {
	return c.client.ListRoomOnlineUsers(ctx, req)
}

func (c *grpcRoomQueryClient) ListRoomBannedUsers(ctx context.Context, req *roomv1.ListRoomBannedUsersRequest) (*roomv1.ListRoomBannedUsersResponse, error) {
	return c.client.ListRoomBannedUsers(ctx, req)
}
