class EasyCurrencyExchangeRate < ActiveRecord::Base

  validates :rate, numericality: { greater_than: 0.to_d }, :allow_nil => true

  validate :validate_date_lock

  belongs_to :base_currency, class_name: :EasyCurrency, primary_key: :iso_code, foreign_key: :base_code
  belongs_to :target_currency, class_name: :EasyCurrency, primary_key: :iso_code, foreign_key: :to_code

  attr_protected :id

  scope :rates_by_iso, ->(base_iso_code, date) { where('valid_on = (SELECT valid_on FROM easy_currency_exchange_rates as sub where sub.to_code = easy_currency_exchange_rates.to_code and easy_currency_exchange_rates.base_code = sub.base_code and valid_on <= coalesce(?, valid_on) ORDER BY valid_on DESC LIMIT 1)', date).where(base_code: base_iso_code).select(:valid_on, :to_code, :rate) }

  def reverse_pair_rate(date)
    (1 / EasyCurrencyExchangeRate.find_exchange_rate(base_currency,target_currency,date).rate.to_d).to_d
  end

  def reverse_pair(date=nil)
    EasyCurrencyExchangeRate.find_exchange_rate(target_currency,base_currency,date)
  end

  def self.find_exchange_rate(base_currency, to_currency, date=nil)
    base_code = base_currency.is_a?(EasyCurrency) ? base_currency.iso_code : base_currency
    target_code = to_currency.is_a?(EasyCurrency) ? to_currency.iso_code : to_currency
    EasyCurrencyExchangeRate.where(base_code: base_code, to_code: target_code).where('( valid_on <= coalesce(?, valid_on) OR valid_on IS NULL)', date).order(valid_on: :desc).limit(1).first
  end

  def self.recalculate(base_currency, to_currency, value, date = nil)
    return value if base_currency.nil? || to_currency.nil? || base_currency == to_currency || !value.is_a?(Numeric)
    if (exchange_rate = self.find_exchange_rate(base_currency, to_currency, date))
      exchange_rate.rate.to_d * value
    else
      value
    end
  end

  def validate_date_lock
    return if EasySetting.value(:easy_currency_exchange_rates).nil? || EasySetting.value(:easy_currency_exchange_rates)[:locked_after_months].blank?
    lock_date = Date.today.advance(months: EasySetting.value(:easy_currency_exchange_rates)[:locked_after_months].to_i * -1 )
    errors.add(:date, l(:date_is_locked)) if lock_date > valid_on
  end

end
