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

  has_one_attached :pdf

  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?

  # NOTE: Multiple status if paing before brinting?
  enum status: {
    open: 0,
    printing: 1,
    ready_for_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 ready_for_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 ready_for_pickup and jobs from today with status: paid canceled
  # paid: only printed_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 ready_for_pickup])
      .or(Job.where(status: %i[paid canceled])
      .where('status_changed_at >= ?', Time.now.beginning_of_day))
      # .in_status_order
      .order(created_at: :asc)
  end

  def fullname
    [costumer_firstname, ' ', costumer_lastname].join
  end

  def acceptable_pdf
    return unless pdf.attached?

    errors.add(:pdf, 'is too big') unless pdf.blob.byte_size <= 100.megabyte

    acceptable_types = ['application/pdf']
    return if acceptable_types.include?(pdf.content_type)

    errors.add(:pdf, 'must be a PDF')
  end

  private

  def update_printed_at
    self.printed_at = Time.now if ready_for_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
end
