class PhotographerPayment < InvoicingRecord
  belongs_to :user, optional: true
  belongs_to :photographer_billing_company, optional: true
  belongs_to :payment_type, optional: true
  has_many :photographer_payment_lines
  has_many :photographer_billings, through: :photographer_payment_lines
  has_many :photographer_billing_lines, through: :photographer_billings
  has_many :photographer_payment_amounts

  belongs_to :cancel_payment, optional: true, class_name: 'PhotographerPayment', foreign_key: 'cancel_payment_id'
  has_one :photographer_payment, foreign_key: 'cancel_payment_id'

  validates :photographer_billing_company_id, :payment_type_id, :payment_date, presence: true
  validates_presence_of :photographer_payment_lines

  before_save :preserve_changes, if: -> { closed? && !hash_string_valid? }
  after_create :create_photographer_payment_amounts

  accepts_nested_attributes_for :photographer_payment_lines, reject_if: -> (attributes) { attributes[:amount].to_f == 0 }, allow_destroy: true

  def cancel_payment?
    (cancel_payment || photographer_payment).present?
  end

  def cancel_payment_params
    attr = attributes.slice(*(PhotographerPayment.column_names - %w[id created_at updated_at]))
    attr['total'] = -attr['total']
    attr['photographer_payment_lines_attributes'] = photographer_payment_lines.map do |line|
      line_attr = line.attributes.slice(*(PhotographerPaymentLine.column_names - %w[id photographer_payment_id created_at updated_at]))
      line_attr['amount'] = -line_attr['amount']
      line_attr
    end
    attr
  end

  def create_photographer_payment_amounts
    payment_ratio = total / photographer_billings.sum(&:total_ttc)
    payment_ratio = 0 if payment_ratio.nan?
    photographer_billing_lines.group_by(&:vat).each do |vat_rate, lines|
      photographer_payment_amounts.create(vat_rate: vat_rate, vat: lines.sum(&:vat_amount) * payment_ratio, total_ht: lines.sum(&:total_ht) * payment_ratio)
    end
  end

  def closed?
    photographer_payment_lines.any?(&:closed?)
  end

  def hash_string_valid?
    photographer_payment_lines.all?(&:hash_string_valid?)
  end

  def preserve_changes
    throw :abort
  end
end
