require 'debci/db'
require 'debci/package'
require 'debci/job'
require 'debci/experiment_test'

module Debci
  class Debci::Experiment < ActiveRecord::Base
    serialize :package_selector, type: Hash
    serialize :control_parameters, type: Hash
    serialize :test_parameters, type: Hash

    has_many :tests, class_name: 'Debci::ExperimentTest'
    belongs_to :owner, class_name: 'Debci::User'

    def packages
      @packages ||= Debci::Package.where(**self.package_selector).order(:name)
    end

    def start
      packages.in_batches do |batch|
        batch.each do |package|
          control_job = Debci::Job.create!(
            suite: suite,
            arch: arch,
            package: package,
            requestor: owner,
            priority: priority,
            **Hash(self.control_parameters)
          )
          test_job = Debci::Job.create!(
            suite: suite,
            arch: arch,
            package: package,
            requestor: owner,
            priority: priority,
            **Hash(self.test_parameters),
          )
          tests.create!(control_job: control_job, test_job: test_job)
          [control_job, test_job].each do |job|
            suite = job.suite
            arch = job.arch
            if package.reject_listed?(suite: suite, arch: arch)
              job.status = 'fail'
              job.date = Time.now
              job.save!
              pkg = package.name
              Debci.warn("#{pkg} (#{suite}/#{arch}) in the reject list, skipping")
              next
            end
            job.enqueue
          end
        end
      end
      update(started_at: Time.now)
    end

    def started?
      !started_at.blank?
    end

    def percent_completed
      complete = 0
      total = 0
      Debci::Job.joins(
        'JOIN experiment_tests ON jobs.run_id in (experiment_tests.control_job_id, experiment_tests.test_job_id)'
      ).where(
        ['experiment_tests.experiment_id = ?', self.id]
      ).pluck(:status).each do |status|
        total += 1
        complete += 1 unless status.nil?
      end
      return 0 unless complete.positive?

      100 * complete.to_f / total.to_f
    end
  end
end
