# frozen_string_literal: true

# Resolves cross-chunk track boundaries and finalizes parallel track generation
# Runs after all chunk processors complete to handle tracks spanning multiple chunks
class Tracks::BoundaryResolverJob < ApplicationJob
  queue_as :tracks

  def perform(user_id, session_id)
    @user = User.find(user_id)
    @session_manager = Tracks::SessionManager.new(user_id, session_id)

    return unless session_exists_and_ready?

    boundary_tracks_resolved = resolve_boundary_tracks
    finalize_session(boundary_tracks_resolved)

  rescue StandardError => e
    ExceptionReporter.call(e, "Failed to resolve boundaries for user #{user_id}")

    mark_session_failed(e.message)
  end

  private

  attr_reader :user, :session_manager

  def session_exists_and_ready?
    return false unless session_manager.session_exists?

    unless session_manager.all_chunks_completed?
      reschedule_boundary_resolution

      return false
    end

    true
  end

  def resolve_boundary_tracks
    boundary_detector = Tracks::BoundaryDetector.new(user)
    boundary_detector.resolve_cross_chunk_tracks
  end

  def finalize_session(boundary_tracks_resolved)
    session_data = session_manager.get_session_data
    total_tracks = session_data['tracks_created'] + boundary_tracks_resolved

    session_manager.mark_completed
  end

  def reschedule_boundary_resolution
    # Reschedule with exponential backoff (max 5 minutes)
    delay = [30.seconds, 1.minute, 2.minutes, 5.minutes].sample

    self.class.set(wait: delay).perform_later(user.id, session_manager.session_id)
  end

  def mark_session_failed(error_message)
    session_manager.mark_failed(error_message)
  end
end
