package handler import ( "net/http" "datarush/internal/gw/domain" "datarush/internal/gw/grpc_client" "datarush/internal/gw/utils" comppb "datarush/pkg/api/competition" ) type CompetitionHandler struct { competitionClient *grpc_client.CompetitionClient userClient *grpc_client.UserClient } func NewCompetitionHandler( competitionClient *grpc_client.CompetitionClient, userClient *grpc_client.UserClient, ) *CompetitionHandler { return &CompetitionHandler{ competitionClient: competitionClient, userClient: userClient, } } func (h *CompetitionHandler) CreateCompetition(w http.ResponseWriter, r *http.Request) { var req domain.CompetitionRequest if err := utils.DecodeJSON(r, &req); err != nil { utils.RespondError(w, err) return } competition := utils.CompetitionHTTPToProto(&req) resp, err := h.competitionClient.CreateCompetition(r.Context(), competition) if err != nil { utils.RespondError(w, domain.NewInternalServerError("failed to create competition")) return } utils.RespondJSON(w, http.StatusCreated, utils.CompetitionProtoToHTTP(resp)) } func (h *CompetitionHandler) GetCompetition(w http.ResponseWriter, r *http.Request) { competitionID := getPathParam(r, "competition_id") competition, err := h.competitionClient.GetCompetition(r.Context(), competitionID) if err != nil { utils.RespondError(w, domain.NewNotFoundError("competition not found")) return } utils.RespondJSON(w, http.StatusOK, utils.CompetitionProtoToHTTP(competition)) } func (h *CompetitionHandler) UpdateCompetition(w http.ResponseWriter, r *http.Request) { competitionID := getPathParam(r, "competition_id") var req domain.CompetitionRequest if err := utils.DecodeJSON(r, &req); err != nil { utils.RespondError(w, err) return } req.ID = competitionID competition := utils.CompetitionHTTPToProto(&req) resp, err := h.competitionClient.EditCompetition(r.Context(), competition) if err != nil { utils.RespondError(w, domain.NewInternalServerError("failed to update competition")) return } utils.RespondJSON(w, http.StatusOK, utils.CompetitionProtoToHTTP(resp)) } func (h *CompetitionHandler) DeleteCompetition(w http.ResponseWriter, r *http.Request) { competitionID := getPathParam(r, "competition_id") if err := h.competitionClient.DeleteCompetition(r.Context(), competitionID); err != nil { utils.RespondError(w, domain.NewInternalServerError("failed to delete competition")) return } w.WriteHeader(http.StatusNoContent) } func (h *CompetitionHandler) ListCompetitions(w http.ResponseWriter, r *http.Request) { pageSize := getQueryParamInt32(r, "page_size", 20) pageToken := getQueryParamInt32(r, "page_token", 0) state := getQueryParam(r, "state") searchQuery := getQueryParam(r, "search_query") isParticipating := getQueryParamBool(r, "is_participating") req := &comppb.ListCompetitionsRequest{ PageSize: pageSize, PageToken: pageToken, } if state != "" { s := utils.StringToCompetitionState(state) req.State = &s } if searchQuery != "" { req.SearchQuery = &searchQuery } if isParticipating != nil { req.IsParticipating = isParticipating } resp, err := h.competitionClient.ListCompetitions(r.Context(), req) if err != nil { utils.RespondError(w, domain.NewInternalServerError("failed to list competitions")) return } competitions := make([]domain.CompetitionResponse, len(resp.Competitions)) for i, comp := range resp.Competitions { competitions[i] = *utils.CompetitionProtoToHTTP(comp) } utils.RespondJSON(w, http.StatusOK, &domain.ListCompetitionsResponse{ TotalCount: resp.TotalCount, NextPageToken: resp.NextPageToken, Competitions: competitions, }) } func (h *CompetitionHandler) ChangeCompetitionState(w http.ResponseWriter, r *http.Request) { competitionID := getPathParam(r, "competition_id") var req domain.ChangeCompetitionStateRequest if err := utils.DecodeJSON(r, &req); err != nil { utils.RespondError(w, err) return } state := utils.StringToCompetitionState(req.State) competition, err := h.competitionClient.ChangeCompetitionState(r.Context(), competitionID, state) if err != nil { utils.RespondError(w, domain.NewInternalServerError("failed to change competition state")) return } utils.RespondJSON(w, http.StatusOK, utils.CompetitionProtoToHTTP(competition)) } func (h *CompetitionHandler) JoinCompetition(w http.ResponseWriter, r *http.Request) { competitionID := getPathParam(r, "competition_id") if err := h.userClient.RegisterForCompetition(r.Context(), competitionID); err != nil { utils.RespondError(w, domain.NewInternalServerError("failed to join competition")) return } w.WriteHeader(http.StatusNoContent) }