class CatarsePaypalExpress::PaypalExpressController < ApplicationController
  include ActiveMerchant::Billing::Integrations

  skip_before_filter :force_http

  SCOPE = "projects.contributions.checkout"
  layout :false

  def review
  end

  def ipn
    if contribution && notification.acknowledge && (contribution.payment_method == 'PayPal' || contribution.payment_method.nil?)
      process_paypal_message params
      contribution.update_attributes({
        :payment_service_fee => params['mc_fee'],
        :payer_email => params['payer_email']
      })
    else
      return render status: 500, nothing: true
    end
    return render status: 200, nothing: true
  rescue Exception => e
    return render status: 500, text: e.inspect
  end

  def pay
    begin
      response = gateway.setup_purchase(contribution.price_in_cents, {
        ip: request.remote_ip,
        return_url: success_paypal_express_url(id: contribution.id),
        cancel_return_url: cancel_paypal_express_url(id: contribution.id),
        currency_code: 'BRL',
        description: t('paypal_description', scope: SCOPE, :project_name => contribution.project.name, :value => contribution.display_value),
        notify_url: ipn_paypal_express_index_url(subdomain: 'www')
      })

      process_paypal_message response.params
      contribution.update_attributes payment_method: 'PayPal', payment_token: response.token

      redirect_to gateway.redirect_url_for(response.token)
    rescue Exception => e
      Rails.logger.info "-----> #{e.inspect}"
      flash[:failure] = t('paypal_error', scope: SCOPE)
      return redirect_to main_app.new_project_contribution_path(contribution.project)
    end
  end

  def success
    begin
      purchase = gateway.purchase(contribution.price_in_cents, {
        ip: request.remote_ip,
        token: contribution.payment_token,
        payer_id: params[:PayerID]
      })

      # we must get the deatils after the purchase in order to get the transaction_id
      process_paypal_message purchase.params
      contribution.update_attributes payment_id: purchase.params['transaction_id'] if purchase.params['transaction_id']

      flash[:success] = t('success', scope: SCOPE)
      redirect_to main_app.project_contribution_path(project_id: contribution.project.id, id: contribution.id)
    rescue Exception => e
      Rails.logger.info "-----> #{e.inspect}"
      flash[:failure] = t('paypal_error', scope: SCOPE)
      return redirect_to main_app.new_project_contribution_path(contribution.project)
    end
  end

  def cancel
    flash[:failure] = t('paypal_cancel', scope: SCOPE)
    redirect_to main_app.new_project_contribution_path(contribution.project)
  end

  def contribution
    @contribution ||= if params['id']
                  PaymentEngines.find_payment(id: params['id'])
                elsif params['txn_id']
                  PaymentEngines.find_payment(payment_id: params['txn_id']) || (params['parent_txn_id'] && PaymentEngines.find_payment(payment_id: params['parent_txn_id']))
                end
  end

  def process_paypal_message(data)
    extra_data = (data['charset'] ? JSON.parse(data.to_json.force_encoding(data['charset']).encode('utf-8')) : data)
    PaymentEngines.create_payment_notification contribution_id: contribution.id, extra_data: extra_data

    if data["checkout_status"] == 'PaymentActionCompleted'
      contribution.confirm!
    elsif data["payment_status"]
      case data["payment_status"].downcase
      when 'completed'
        contribution.confirm!
      when 'refunded'
        contribution.refund!
      when 'canceled_reversal'
        contribution.cancel!
      when 'expired', 'denied'
        contribution.pendent!
      else
        contribution.waiting! if contribution.pending?
      end
    end
  end

  def gateway
    @gateway ||= CatarsePaypalExpress::Gateway.instance
  end

  protected

  def notification
    @notification ||= Paypal::Notification.new(request.raw_post)
  end
end