module Public
  class RegiaController < SiteBaseController
    include Public::LiveHelper

    layout "regia"

    protect_from_forgery with: :null_session
    skip_before_action :verify_authenticity_token, only: %i[score pause stop]

    before_action :set_session_from_token

    def show
      @match = @session.match
      @team = @match.team
      @score = @session.score_state || @session.create_score_state!(
        home_sets: 0, away_sets: 0, home_points: 0, away_points: 0, current_set: 1, set_partials: []
      )
      @rules = Scoring::Rules.from_match(@match)
      @stream_closed = @session.terminal?
      @on_air = !@stream_closed && mediamtx_online?(@session)
      @share_url = request.original_url
      @share_title = "Regia — #{@team.name} vs #{@match.opponent_name}"
    end

    def status
      render json: status_payload
    end

    def score
      cmd = params[:cmd].presence || params[:score_action].presence
      result = Scoring::ApplyAction.new(session: @session, action: cmd).call
      render json: status_payload.merge(
        set_won: result.set_won,
        match_won: result.match_won,
        winner: result.winner&.to_s
      )
    rescue ArgumentError => e
      render json: { error: e.message }, status: :unprocessable_entity
    end

    def pause
      Sessions::Pause.new(@session).call
      render json: status_payload
    end

    def stop
      Sessions::Stop.new(@session).call
      render json: status_payload
    end

    private

    def set_session_from_token
      @session = Sessions::RegiaAccess.find_session_by_token(params[:token])
      return if @session

      render file: Rails.root.join("public/404.html"), status: :not_found, layout: false
      throw :abort
    end

    def status_payload
      score = @session.score_state
      closed = @session.terminal?
      {
        status: @session.status,
        stream_closed: closed,
        live: !closed && (@session.live? || mediamtx_online?(@session)),
        on_air: !closed && mediamtx_online?(@session),
        ended_at: @session.ended_at,
        home_name: @session.match.team.name,
        away_name: @session.match.opponent_name,
        points_target: Scoring::Rules.from_match(@session.match).points_target(score&.current_set || 1),
        score: score&.as_cable_payload
      }
    end

    def mediamtx_online?(session)
      @online_paths_cache ||= Mediamtx::Client.new.online_path_names
      @online_paths_cache.include?(session.mediamtx_path_name)
    end
  end
end
