# https://www.ccbill.com/cs/wiki/tiki-index.php?page=Background+Post
class Effective::Providers::CcbillPostback
  attr_reader :params

  def initialize(params)
    @params = params
  end

  def verified?
    params[:responseDigest] == digest(digest_value)
  end

  def matches?(order)
    price == order.total && order_id == order.to_param
  end

  def approval?
    !denial?
  end

  def denial?
    # denialId is for subscriptions only
    [:reasonForDeclineCode, :reasonForDecline, :denialId].any? { |key| params[key].present? }
  end

  def order_details
    @order_details ||= get_order_details
  end

  def order_id
    params[:order_id]
  end

  private

  # https://www.ccbill.com/cs/wiki/tiki-index.php?page=Dynamic+Pricing+User+Guide#Postback
  def digest_value
    if approval?
      "#{params[:subscription_id]}1#{salt}" # the `subscriptionId` param in the linked docs is a typo
    else
      "#{params[:denialId]}0#{salt}"
    end
  end

  def digest(value)
    Digest::MD5.hexdigest(value)
  end

  def salt
    EffectiveOrders.ccbill[:dynamic_pricing_salt]
  end

  # in cents
  def price
    return @price if @price.present?
    formatted_price = params[:initialFormattedPrice] # example: "$10.00"
    formatted_price = Nokogiri::HTML::DocumentFragment.parse(formatted_price).to_s # => "$10.00"
    match = formatted_price.match(/^\D(\d*.\d\d)$/) # {a currency symbol}(digits.two digits)
    return false unless match.present?
    formatted_price = match[1] # => "10.00"
    @price = formatted_price.sub('.', '').to_i # => 1000
  end

  def get_order_details
    # ignore some params
    keepable = params.except(*ignorable_params)
    # remove blanks
    keepable.inject({}) do |details, kv_pair|
      details[kv_pair[0]] = kv_pair[1] if kv_pair[1].present?
      details
    end
  end

  def ignorable_params
    [
      # we have these already
      :clientAccnum,
      :clientSubacc,
      :productDesc,
      # a hash of billing information which CCBill doesn't share the format of (afaik)
      :paymentAccount
    ]
  end
end