class Billing < InvoicingRecord
  belongs_to :billing_type, optional: true
  belongs_to :billing_company, optional: true
  belongs_to :discount_type, optional: true
  belongs_to :price_type, optional: true
  belongs_to :logo, optional: true
  belongs_to :credit_note, optional: true, class_name: 'Billing', foreign_key: 'credit_note_id'
  has_one :billing, foreign_key: 'credit_note_id'
  has_many :billing_lines, dependent: :destroy
  has_many :images, through: :billing_lines
  has_many :payment_lines, dependent: :destroy

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

  validates :billing_type_id, :billing_company_id, :discount_type_id,
            :number, :sub_number, :date, :deadline, presence: true

  before_save :set_state
  before_save :set_synced_to_4d

  accepts_nested_attributes_for :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
    [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(: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(: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 = 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 statement_inside?
    billing_lines.any? { |l| l.photographer_rate.to_f > 0 }
  end

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

  def credit_note_params
    attr = attributes.slice(*%w[date deadline billing_company_id price_type_id discount_type_id conditions total_before_discount discount total general_discount total_ht_final vat total_ttc heading logo_id])
    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['billing_lines_attributes'] = billing_lines.map do |line|
      line_attr = line.attributes.slice(*%w[product_type_id image_id description right_owner_id photographer_rate 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 billing_company_id price_type_id discount_type_id conditions total_before_discount discount total general_discount total_ht_final vat total_ttc heading logo_id])
    today = Date.today
    deadline = today + billing_company&.time_limit.to_i.day
    deadline = deadline.end_of_month if billing_company&.end_of_month
    attr['date'] = today
    attr['deadline'] = deadline
    attr['billing_lines_attributes'] = billing_lines.map do |line|
      line.attributes.slice(*%w[product_type_id image_id description right_owner_id photographer_rate 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

  def set_synced_to_4d
    self.synced_to_4d = false
  end
end
