module Spree
  module Api
    module V1
      class PaymentsController < Spree::Api::BaseController
        before_action :find_order
        before_action :find_payment, only: [:update, :show, :authorize, :purchase, :capture, :void]

        def index
          @payments = @order.payments.ransack(params[:q]).result.page(params[:page]).per(params[:per_page])
          respond_with(@payments)
        end

        def new
          @payment_methods = Spree::PaymentMethod.available
          respond_with(@payment_methods)
        end

        def create
          @order.validate_payments_attributes([payment_params])
          @payment = @order.payments.build(payment_params)
          if @payment.save
            respond_with(@payment, status: 201, default_template: :show)
          else
            invalid_resource!(@payment)
          end
        end

        def update
          authorize! params[:action], @payment
          if !@payment.editable?
            render 'update_forbidden', status: 403
          elsif @payment.update_attributes(payment_params)
            respond_with(@payment, default_template: :show)
          else
            invalid_resource!(@payment)
          end
        end

        def show
          respond_with(@payment)
        end

        def authorize
          perform_payment_action(:authorize)
        end

        def capture
          perform_payment_action(:capture)
        end

        def purchase
          perform_payment_action(:purchase)
        end

        def void
          perform_payment_action(:void_transaction)
        end

        private

        def find_order
          @order = Spree::Order.find_by!(number: order_id)
          authorize! :read, @order, order_token
        end

        def find_payment
          @payment = @order.payments.find_by!(number: params[:id])
        end

        def perform_payment_action(action, *args)
          authorize! action, Payment
          @payment.send("#{action}!", *args)
          respond_with(@payment, default_template: :show)
        end

        def payment_params
          params.require(:payment).permit(permitted_payment_attributes)
        end
      end
    end
  end
end
