class Job < ApplicationRecord
  belongs_to :operator, class_name: "User", optional: true
  belongs_to :costumer, class_name: "User", optional: true

  has_one_attached :pdf, dependent: :purge

  validates_presence_of :costumer_firstname, :costumer_lastname, :privacy_policy_accepted, :pdf
  validate :acceptable_pdf

  before_save :update_printed_at, if: :will_save_change_to_status?
  before_save :update_paid_at, if: :will_save_change_to_status?
  before_save :update_status_changed_at, if: :will_save_change_to_status?
  before_save :set_cost_qm

  # TODO: works only when job is created. Should move analyzer to activestorage :https://discuss.rubyonrails.org/t/active-storage-in-production-lessons-learned-and-in-depth-look-at-how-it-works/83289
  after_create_commit :analyze_pdf

  # NOTE: Multiple status if paing before brinting?
  enum status: {
    open: 0,
    printing: 1,
    pickup: 2,
    paid: 3,
    canceled: 4
  }

  # NOTE: only named status are returned because of WHERE/IN clause for the enum values
  scope :in_status_order, -> { in_order_of(:status, %w[open printing pickup paid canceled]) }

  scope :created_today, -> { created_on_day(Time.now) }
  scope :created_on_day, lambda { |date|
                           where("created_at >= ? AND created_at <= ?", date.beginning_of_day, date.end_of_day)
                         }
  scope :upgraded_today, -> { upgraded_on_day(Time.now) }
  scope :upgraded_on_day, lambda { |date|
                            where("upgraded_at >= ? AND upgraded_at <= ?", date.beginning_of_day, date.end_of_day)
                          }
  # Returns all jobs with status: open print pickup and jobs from today with status: paid canceled
  # paid: only updated_at today
  # canceled: only updated_at today
  def self.currently_working_on
    # NOTE: use Time.now instead of Date.today to take the timezone into account
    where(status: %i[open printing pickup])
      .or(Job.where(status: %i[paid canceled])
      .where("status_changed_at >= ?", Time.now.beginning_of_day))
      # .in_status_order
      .order(created_at: :desc)
      .order(:costumer_firstname, :costumer_lastname)
      .with_attached_pdf # scope from activestorage for .includes(pdf_attachment: :blob)
    # .references(:pdf_attachment, :blob) # creates big join table
  end

  def costumer_fullname
    [ costumer_firstname, " ", costumer_lastname ].join
  end

  def acceptable_pdf
    return unless pdf.attached?

    acceptable_types = [ "application/pdf" ]

    errors.add(:pdf, "is too big") unless pdf.blob.byte_size <= 100.megabyte
    errors.add(:pdf, "must be a PDF") unless acceptable_types.include?(pdf.content_type)
  end

  def able_to_cancel?
    open?
  end

  # cancel job only if it is still open
  def canceled!
    self.status = :canceled if open?
    save
  end

  private

  def update_printed_at
    self.printed_at = Time.now if pickup? || (paid? && printed_at.nil?)
  end

  def update_paid_at
    self.paid_at = Time.now if paid?
  end

  def update_status_changed_at
    self.status_changed_at = Time.now
  end

  def calc_cost
    self.cost = (number_of_plans_a0 * cost_qm) + (number_of_plans_a1 * cost_qm / 2) +
                (number_of_plans_a2 * cost_qm / 4) + (number_of_plans_a3 * cost_qm / 8) +
                (costum_qm_plan * cost_qm)
  end

  def set_cost_qm
    # TODO: get cost from global settings
    self.cost_qm = 7
  end

  def analyze_pdf
    # return unless pdf.attached? && pdf.new_record?
    self.number_of_plans_a0 = 0
    self.number_of_plans_a1 = 0
    self.number_of_plans_a2 = 0
    self.number_of_plans_a3 = 0
    self.costum_qm_plan = 0

    # TODO: add any check if attachment has changed

    # pdfs.each do |pdf|
    pdf.blob.open do |file|
      # file = ActiveStorage::Blob.service.path_for(pdf.key).to_s
      pdf_analyzer = Services::PdfAnalyzer.new(file)
      pdf_analyzer.analyze
      self.number_of_plans_a0 += pdf_analyzer.pages_a0
      self.number_of_plans_a1 += pdf_analyzer.pages_a1
      self.number_of_plans_a2 += pdf_analyzer.pages_a2
      self.number_of_plans_a3 += pdf_analyzer.pages_a3
      self.costum_qm_plan += pdf_analyzer.costum_qm
    end
    # end
    calc_cost
    save
  end
end
