module Api
  module V1
    class StreamSessionsController < BaseController
      before_action :set_session, except: :create

      def create
        team_ids = current_user.streamable_teams.map(&:id)
        match = Match.where(team_id: team_ids).find(params[:match_id])
        session = Sessions::Create.new(user: current_user, match: match, params: session_params).call
        render json: session_json(session), status: :created
      end

      def show
        render json: session_json(@session, detail: true)
      end

      def start
        Sessions::Start.new(@session).call
        render json: session_json(@session)
      end

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

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

      def events
        events = @session.stream_events.recent.limit(100)
        render json: events.map { |e| event_json(e) }
      end

      def telemetry
        role = params.require(:device_role)
        state = @session.device_states.find_or_initialize_by(device_role: role)
        state.update!(
          battery_level: params[:battery_level],
          network_type: params[:network_type],
          signal_strength: params[:signal_strength],
          current_bitrate: params[:current_bitrate],
          target_bitrate: params[:target_bitrate],
          fps: params[:fps],
          last_seen_at: Time.current
        )
        SessionChannel.broadcast_message(@session, state.as_cable_payload)
        head :no_content
      end

      def pairing_token
        token = SecureRandom.urlsafe_base64(24)
        @session.update!(
          pairing_token_digest: Digest::SHA256.hexdigest(token),
          pairing_token_expires_at: 15.minutes.from_now
        )
        render json: {
          pairing_token: token,
          expires_at: @session.pairing_token_expires_at,
          qr_payload: {
            session_id: @session.id,
            pairing_token: token,
            api_url: request.base_url
          }
        }
      end

      def regia_link
        access = Sessions::RegiaAccess.new(@session)
        token = access.issue_token!
        render json: {
          regia_url: access.url(token),
          expires_at: @session.regia_token_expires_at
        }
      end

      def claim_pairing
        token = params.require(:pairing_token)
        digest = Digest::SHA256.hexdigest(token)
        unless @session.pairing_token_digest == digest &&
               @session.pairing_token_expires_at&.future?
          return render json: { error: "Invalid or expired token" }, status: :unauthorized
        end

        @session.device_states.find_or_create_by!(device_role: params[:device_role] || "controller")
        render json: session_json(@session)
      end

      def network_test
        @session.stream_events.create!(
          event_type: "network_test",
          metadata: params.permit(:download_mbps, :upload_mbps, :latency_ms, :network_type).to_h,
          occurred_at: Time.current
        )
        ready = params[:upload_mbps].to_f >= (@session.target_bitrate / 1_000_000.0 * 0.8)
        render json: { ready: ready, target_upload_mbps: @session.target_bitrate / 1_000_000.0 }
      end

      def youtube_stats
        count = if @session.platform == "youtube" && @session.youtube_broadcast_id.present?
                  Youtube::BroadcastService.new(@session.match.team)
                                           .viewer_count(@session.youtube_broadcast_id)
                else
                  0
                end
        render json: { concurrent_viewers: count, live: @session.live? }
      end

      private

      def set_session
        team_ids = current_user.streamable_teams.map(&:id)
        @session = StreamSession.joins(:match)
                                .where(matches: { team_id: team_ids })
                                .find(params[:id])
      end

      def session_params
        params.permit(:platform, :privacy_status, :quality_preset, :target_bitrate, :target_fps)
      end

      def session_json(session, detail: false)
        data = {
          id: session.id,
          match_id: session.match_id,
          status: session.status,
          platform: session.platform,
          rtmp_ingest_url: session.rtmp_ingest_url,
          hls_playback_url: session.hls_playback_url,
          watch_page_url: session.watch_page_url,
          youtube_broadcast_id: session.youtube_broadcast_id,
          privacy_status: session.privacy_status,
          quality_preset: session.quality_preset,
          target_bitrate: session.target_bitrate,
          started_at: session.started_at,
          disconnection_count: session.disconnection_count
        }
        if detail
          data[:score] = session.score_state&.as_cable_payload
          data[:devices] = session.device_states.map(&:as_cable_payload)
        end
        data
      end

      def event_json(event)
        {
          id: event.id,
          event_type: event.event_type,
          metadata: event.metadata,
          occurred_at: event.occurred_at
        }
      end
    end
  end
end
