require 'jenkins_job_scraper'

class QueueTimeMonitorJob
  include Sidekiq::Worker
  sidekiq_options :retry => 1

  def perform(queue_time_monitor_id, source_job_name, source_job_number, builds_to_search=10, max_attempts=240)
    jenkins_username = Rails.application.secrets.jenkins_username || ENV['JENKINS_USERNAME']
    jenkins_token    = Rails.application.secrets.jenkins_token    || ENV['JENKINS_TOKEN']
    @scraper = JenkinsJobScraper.new('qa-smoca', jenkins_username, jenkins_token)

    record_found = false
    attempts = 0
    while !record_found && (attempts < max_attempts) do
      attempts += 1

      last_build_number = @scraper.last_build_number
      logger.info "Last Build Number: #{last_build_number}"

      for build in 0...(builds_to_search)
        build_number = last_build_number - build

        if matching_job?(build_number, source_job_name, source_job_number)
          timestamp = parse_timestamp(build_info(build_number)['timestamp'])

          r = QueueTimeMonitor.find(queue_time_monitor_id)
          r.update!(smoca_build_number: build_number, smoca_initiated_at: timestamp)
          record_found = true
          logger.info "Match found for #{build_number}"
        else
          logger.info "Build \##{build_number} was not matching #{source_job_name}:#{source_job_number}, attempt \##{attempts}"
        end

        break if record_found
      end
      sleep(60) unless record_found # Try again in 60 seconds
    end

    if record_found == false
      raise "Max attempts expired for #{source_job_name} \##{source_job_number}, ID: #{queue_time_monitor_id}"
    end
  end

  def matching_job?(build_number, source_job_name, source_job_number)
    build_info_response = build_info(build_number)
    return false if build_info_response.nil? # Nil is returned if build wasn't found

    upstream_project = build_info_response['upstreamProject']
    upstream_build = build_info_response['upstreamBuild']

    logger.info "Upstream Data for \##{build_number}: Project #{upstream_project}, Build #{upstream_build} "
    return (upstream_project == source_job_name) && (upstream_build == source_job_number.to_i)
  end

  private def build_info(build_number)
    begin
      return @scraper.get_build_info(build_number)
    rescue Exception => e
      logger.warn "Encountered exception: #{e.message}. Sleeping for 60 seconds, trying again."
      sleep(60)
      return @scraper.get_build_info(build_number)
    end
  end

  def parse_timestamp(timestamp)
    return DateTime.strptime(timestamp, '%Q')
  end
end
