class PhotographerBilling < InvoicingRecord
  belongs_to :user, optional: true
  belongs_to :billing_type, optional: true
  belongs_to :photographer_billing_company, optional: true
  belongs_to :discount_type, optional: true
  belongs_to :price_type, optional: true
  belongs_to :credit_note, optional: true, class_name: 'PhotographerBilling', foreign_key: 'credit_note_id'
  has_one :photographer_billing, foreign_key: 'credit_note_id'
  has_many :photographer_billing_lines
  has_many :images, through: :photographer_billing_lines
  has_many :photographer_payment_lines

  scope :payment_available, -> { where('state IN (?)', [:ready, :processing]) }

  validates :user_id, :billing_type_id, :photographer_billing_company_id, :discount_type_id,
            :number, :sub_number, :date, :deadline, presence: true

  before_save :set_state

  accepts_nested_attributes_for :photographer_billing_lines, allow_destroy: true

  def full_number
    [number, sub_number].compact.join('/')
  end

  def full_code
    [billing_type&.code, full_number].compact.join(' ')
  end

  def full_name
    [user&.full_code, billing_type&.name, full_number].compact.join('-')
  end

  def rest
    return [0, total_ttc.to_f - paid.to_f].min if billing_type&.credit_note?
    [0, (total_ttc.to_f - paid.to_f).round(3)].max
  end

  def set_provision_number
    self.state = :pending
    self.number = Date.today.year
    sub_number = self.class.where(:user_id => user_id, :number => number).pluck(:sub_number).map(&:to_i).min || 0
    self.sub_number = if sub_number.to_i >= 0
                        -1
                      else
                        sub_number - 1
                      end
  end


  def set_permanent_number
    self.state = :ready
    self.number = Date.today.year
    sub_number = self.class.where(:user_id => user_id, :number => number).pluck(:sub_number).map(&:to_i).max || 0
    self.sub_number = if sub_number <= 0
                        1
                      else
                        sub_number + 1
                      end
  end

  def pending?
    state == 'pending'
  end

  def ready?
    state == 'ready'
  end

  def done?
    state == 'done'
  end

  def avoir?
    b = photographer_billing || credit_note
    b.present? && b.ready? && paid.to_f + b.paid.to_f == 0 && total_ttc.to_f + b.total_ttc.to_f == 0
  end

  def create_credit_note?
    !pending? && billing_type&.invoice?
  end

  def credit_note_params
    attr = attributes.slice(*%w[date deadline photographer_billing_company_id discount_type_id conditions total_before_discount discount total general_discount total_ht_final vat total_ttc heading])
    attr['billing_type_id'] = 1
    %w[total_before_discount discount total general_discount total_ht_final vat total_ttc].each { |k| attr[k] = -attr[k] }
    attr['photographer_billing_lines_attributes'] = photographer_billing_lines.map do |line|
      line_attr = line.attributes.slice(*%w[product_type_id image_id description quantity price vat discount total_ht total_ttc retribution usage])
      %w[price discount total_ht total_ttc].each { |k| line_attr[k] = -line_attr[k] }
      line_attr
    end
    attr
  end

  def duplicate_params
    attr = attributes.slice(*%w[billing_type_id user_id photographer_billing_company_id discount_type_id conditions total_before_discount discount total general_discount total_ht_final vat total_ttc heading])
    today = Date.today
    deadline = today + photographer_billing_company&.time_limit.to_i.day
    deadline = deadline.end_of_month if photographer_billing_company&.end_of_month
    attr['date'] = today
    attr['deadline'] = deadline
    attr['photographer_billing_lines_attributes'] = photographer_billing_lines.map do |line|
      line.attributes.slice(*%w[product_type_id image_id description quantity price vat discount total_ht total_ttc retribution usage])
    end
    attr
  end

  private

  def set_state
    self.state = if sub_number.include?('-')
                   :pending
                 elsif paid.to_f == 0
                   :ready
                 elsif rest > 0
                   :processing
                 else
                   :done
                 end
  end
end
