package server import ( "net/http" "galaxy/backend/internal/lobby" "galaxy/backend/internal/server/handlers" "galaxy/backend/internal/server/httperr" "galaxy/backend/internal/server/middleware/userid" "github.com/gin-gonic/gin" "go.uber.org/zap" ) // UserLobbyMyHandlers groups the caller-scoped lobby read endpoints // under `/api/v1/user/lobby/my/*`. The current implementation ships real implementations // backed by `*lobby.Service`. type UserLobbyMyHandlers struct { svc *lobby.Service logger *zap.Logger } // NewUserLobbyMyHandlers constructs the handler set. svc may be nil — // in that case every handler returns 501 not_implemented. func NewUserLobbyMyHandlers(svc *lobby.Service, logger *zap.Logger) *UserLobbyMyHandlers { if logger == nil { logger = zap.NewNop() } return &UserLobbyMyHandlers{svc: svc, logger: logger.Named("http.user.lobby.my")} } // Games handles GET /api/v1/user/lobby/my/games. func (h *UserLobbyMyHandlers) Games() gin.HandlerFunc { if h.svc == nil { return handlers.NotImplemented("userLobbyMyGames") } return func(c *gin.Context) { userID, ok := userid.FromContext(c.Request.Context()) if !ok { httperr.Abort(c, http.StatusBadRequest, httperr.CodeInvalidRequest, "X-User-ID header is required") return } ctx := c.Request.Context() games, err := h.svc.ListMyGames(ctx, userID) if err != nil { respondLobbyError(c, h.logger, "user lobby my games", ctx, err) return } out := myGamesListResponseWire{Items: make([]gameSummaryWire, 0, len(games))} for _, g := range games { out.Items = append(out.Items, gameSummaryToWire(g)) } c.JSON(http.StatusOK, out) } } // Applications handles GET /api/v1/user/lobby/my/applications. func (h *UserLobbyMyHandlers) Applications() gin.HandlerFunc { if h.svc == nil { return handlers.NotImplemented("userLobbyMyApplications") } return func(c *gin.Context) { userID, ok := userid.FromContext(c.Request.Context()) if !ok { httperr.Abort(c, http.StatusBadRequest, httperr.CodeInvalidRequest, "X-User-ID header is required") return } ctx := c.Request.Context() items, err := h.svc.ListMyApplications(ctx, userID) if err != nil { respondLobbyError(c, h.logger, "user lobby my applications", ctx, err) return } out := lobbyApplicationListWire{Items: make([]lobbyApplicationDetailWire, 0, len(items))} for _, a := range items { out.Items = append(out.Items, lobbyApplicationDetailToWire(a)) } c.JSON(http.StatusOK, out) } } // Invites handles GET /api/v1/user/lobby/my/invites. func (h *UserLobbyMyHandlers) Invites() gin.HandlerFunc { if h.svc == nil { return handlers.NotImplemented("userLobbyMyInvites") } return func(c *gin.Context) { userID, ok := userid.FromContext(c.Request.Context()) if !ok { httperr.Abort(c, http.StatusBadRequest, httperr.CodeInvalidRequest, "X-User-ID header is required") return } ctx := c.Request.Context() items, err := h.svc.ListMyInvites(ctx, userID) if err != nil { respondLobbyError(c, h.logger, "user lobby my invites", ctx, err) return } out := lobbyInviteListWire{Items: make([]lobbyInviteDetailWire, 0, len(items))} for _, i := range items { out.Items = append(out.Items, lobbyInviteDetailToWire(i)) } c.JSON(http.StatusOK, out) } } // RaceNames handles GET /api/v1/user/lobby/my/race-names. func (h *UserLobbyMyHandlers) RaceNames() gin.HandlerFunc { if h.svc == nil { return handlers.NotImplemented("userLobbyMyRaceNames") } return func(c *gin.Context) { userID, ok := userid.FromContext(c.Request.Context()) if !ok { httperr.Abort(c, http.StatusBadRequest, httperr.CodeInvalidRequest, "X-User-ID header is required") return } ctx := c.Request.Context() items, err := h.svc.ListMyRaceNames(ctx, userID) if err != nil { respondLobbyError(c, h.logger, "user lobby my race-names", ctx, err) return } out := raceNameListWire{Items: make([]raceNameDetailWire, 0, len(items))} for _, e := range items { out.Items = append(out.Items, raceNameDetailToWire(e)) } c.JSON(http.StatusOK, out) } } // Wire envelopes for caller-scoped lists. // myGamesListResponseWire mirrors `MyGamesListResponse`. type myGamesListResponseWire struct { Items []gameSummaryWire `json:"items"` } // lobbyApplicationListWire mirrors `LobbyApplicationList`. type lobbyApplicationListWire struct { Items []lobbyApplicationDetailWire `json:"items"` } // lobbyInviteListWire mirrors `LobbyInviteList`. type lobbyInviteListWire struct { Items []lobbyInviteDetailWire `json:"items"` } // raceNameListWire mirrors `RaceNameList`. type raceNameListWire struct { Items []raceNameDetailWire `json:"items"` }