module Api module V1 class MatchesController < BaseController include Api::UrlHelper include BrandingAttachments before_action :set_team, only: %i[index create] before_action :set_match, only: %i[show update destroy] def index matches = @team.matches .includes(:team, :stream_sessions) .order(Arel.sql("scheduled_at ASC NULLS LAST"), created_at: :desc) .select(&:coach_hub_visible?) render json: matches.map { |m| match_json(m) } end def create attrs = match_params.to_h attrs["sport_key"] = @team.sport_key if attrs["sport_key"].blank? normalize_scoring_rules!(attrs) match = @team.matches.create!(attrs) attach_opponent_logo(match) render json: match_json(match), status: :created end def show render json: match_json(@match, detail: true) end def update attrs = match_params.to_h normalize_scoring_rules!(attrs) normalize_opponent_color!(attrs) @match.update!(attrs) attach_opponent_logo(@match) render json: match_json(@match) end def destroy active = active_session_for(@match) if active&.resumable? return render json: { error: "Chiudi la diretta prima di eliminare questa partita" }, status: :unprocessable_entity end @match.destroy! head :no_content end private def set_team @team = current_user.streamable_teams.find { |t| t.id == params[:team_id] } raise ActiveRecord::RecordNotFound unless @team end def set_match team_ids = current_user.streamable_teams.map(&:id) @match = Match.includes(:team).where(team_id: team_ids).find(params[:id]) end def match_params p = params.require(:match).permit( :opponent_name, :location, :scheduled_at, :sport, :sport_key, :sets_to_win, :category, :opponent_primary_color, :overlay_kind, scoring_rules: {} ) if p[:sport].present? && p[:sport_key].blank? p[:sport_key] = p.delete(:sport) end p end def normalize_scoring_rules!(attrs) return unless attrs.key?("scoring_rules") rules = attrs["scoring_rules"] attrs["scoring_rules"] = {} if rules.blank? if attrs["sets_to_win"].present? && attrs["scoring_rules"].is_a?(Hash) attrs["scoring_rules"]["sets_to_win"] ||= attrs["sets_to_win"] end end def normalize_opponent_color!(attrs) return unless attrs.key?("opponent_primary_color") attrs["opponent_primary_color"] = normalize_hex_color( attrs["opponent_primary_color"], Match::DEFAULT_OPPONENT_COLOR ) end def attach_opponent_logo(match) file = params[:opponent_logo_file] match.opponent_logo_file.attach(file) if file.present? end def match_json(match, detail: false) active = active_session_for(match) team = match.team { id: match.id, team_id: match.team_id, team_name: team.name, opponent_name: match.opponent_name, location: match.location, scheduled_at: match.scheduled_at, sport: match.sport_key, sport_key: match.sport_key, sport_label: match.sport_label, board_type: match.effective_board_type, overlay_kind: match.overlay_kind, effective_overlay_kind: match.effective_overlay_kind, sets_to_win: match.sets_to_win, scoring_rules: match.scoring_rules.presence, effective_scoring_rules: match.effective_scoring_rules, category: match.category, home_primary_color: team.effective_primary_color, home_secondary_color: team.effective_secondary_color, home_logo_url: api_absolute_url(team.effective_logo_url), opponent_primary_color: match.effective_opponent_primary_color, opponent_logo_url: api_absolute_url(match.opponent_logo_url), active_session_id: active&.id, active_session_status: active&.status, stream_completed: match.stream_completed?, coach_hub_visible: match.coach_hub_visible? } end def active_session_for(match) match.stream_sessions .order(created_at: :desc) .find { |s| !%w[ended error].include?(s.status) } end end end end