module MidasClient

  class Subscription < Request
    include EndPoints

    # This method creates a subscription.
    # It is a synchronous operation, using method POST
    #
    # Params:
    #   externalId: string (Transaction identification on the client application)
    #   externalDate: [optional] datetime from client application - YYYY-MM-DDThh:mm:SS.sssTDZ - ISO8601
    #   frequencyType string Is the frequency about the charge will run. Possible values: DAY/WEEK/MONTH
    #   frequencyInterval integer The interval that will be used.
    #   startDate datetime for the beginning of subscription - yyyy-MM-dd
    #   invoicesCount integer - number of invoices for the subscription
    #   amount: number (Only integer numbers, with the last two digits representing the cents.
    #                   For example: 100 is equivalent to R$ 1,00)
    #   cardToken: string (created by method card_store)
    #   cvv: number (Security Code)
    #   callbackUrl string - URL to receive the result for each invoice charge
    #
    # Response:
    # {
    #    "result": {
    #        "success": "true",
    #        "code": "0",
    #        "message": "Sucesso"
    #    },
    #    "subscriptionToken": "49ac54257eb1f92f"
    # }
    #
    #
    # Response with first payment
    # {
    #    "result": {
    #        "success": "true",
    #        "code": "0",
    #        "message": "Sucesso"
    #    },
    #    "subscriptionToken": "49ac54257eb1f92f",
    #    "firstInvoiceResult": {
    #        "success": true,
    #        "code": "000",
    #        "message": "Sucesso"
    #    }
    # }
    #
    #
    # Error response
    #{
    # "result": {
    #      "success": "false",
    #      "code": "114",
    #      "message": "O token do cartao é obrigatório"
    #  }
    #}
    #
    def create_subscription(*params)
      # Parametros são recebidos como um array de hash, pego o 1o item do array
      params = params.first

      # define o método de envio da requisição
      method = :post

      # monta a URL de chamada da requisição
      endpoint=  EndPoints.get_env[:url] + EndPoints.get_env[:context] + EndPoints::SUBSCRIPTIONS[:create]


      params[:externalDate] = (params[:externaldate].blank? ? Time.now.iso8601(1) : params[:externaldate])
      params[:invoicesCount]= (params[:invoicesCount].blank? ? 12 : params[:invoicesCount])

      # faz a chamada a plataforma de pagamento (MIDAS)
      response = request(method, endpoint, self.login, self.password, params)

      result = response[:result]
      subscription_token = response[:subscriptionToken]
      first_invoice_result = response[:firstInvoiceResult]

      return result, subscription_token, first_invoice_result
    end

    # This method cancel a subscription.
    # This is a is synchronous operation.
    #
    # Params:
    #   subscriptionToken: string (Subscription unique identification generated by our
    #                             gateway and received in the subscription's creation response)
    #
    # Response:
    #   result: {
    #     success: true/false
    #     code: "XXX"
    #     message: "Some message to you"
    #   }
    def cancel_subscription(subscription_token)
      # define o método de envio da requisição
      method = :put

      # monta a URL de chamada da requisição
      endpoint =  EndPoints.get_env[:url] + EndPoints.get_env[:context] + EndPoints::SUBSCRIPTIONS[:cancel].gsub('{subscriptionToken}', subscription_token)

      # faz a chamada a plataforma de pagamento (MIDAS)
      response = request(method, endpoint, self.login, self.password, {})

      response[:result]
    end

    # This method updates a subscription callback, amount and updates opened invoices' amount.
    # This is a is synchronous operation.
    #
    # Params:
    #   subscriptionToken: querystring (Subscription unique identification generated by our
    #                             gateway and received in the subscription's creation response)
    #   amount: number (Only integer numbers, with the last two digits representing the cents.
    #                   For example: 100 is equivalent to R$ 1,00)
    #   callbackUrl string - URL to receive the result for each invoice charge
    #
    # Response:
    #   result: {
    #     success: true/false
    #     code: "XXX"
    #     message: "Some message to you"
    #   }
    def update_subscription(subscription_token, params)
      # define o método de envio da requisição
      method = :put

      # monta a URL de chamada da requisição
      endpoint =  EndPoints.get_env[:url] + EndPoints.get_env[:context] + EndPoints::SUBSCRIPTIONS[:update].gsub('{subscriptionToken}', subscription_token)

      # faz a chamada a plataforma de pagamento (MIDAS) para atualizar o valor de face e callback da assinatura
      response = request(method, endpoint, self.login, self.password, params)

      # recupera a lista de invoices da assinatura para chamar o método de atualização de cada invoice.
      invoices = subscription_invoices(subscription_token)

      # filtra apenas as invoices em aberto
      opened_invoices = invoices[:invoices].select{|s| s[:status] == 'OPEN'}

      # percorre cada uma das invoices abertas e chama o método de atualização
      opened_invoices.each do |inv|
        update_invoice(inv[:token], {amount: params[:amount]})
      end

      response[:result]
    end

    # This method performs a query by a specific transaction.
    # This is a is synchronous operation, using method GET
    #
    # Params:
    #   subscription_token: string (Transaction unique identification generated by our
    #                             gateway and received in the subscription's create response)#
    #
    #
    # Response:
    # {
    #   :result=>{
    #     :success=>true,
    #     :code=>"000",
    #     :message=>"Sucesso"
    #   },
    #   :subscription=>{
    #     :externalId=>"10011",
    #     :frequencyType=>"MONTH",
    #     :frequencyInterval=>1,
    #     :startDate=>"2016-07-28T00:00:00.000-04",
    #     :invoicesCount=>12,
    #     :paymentMethod=>"CREDIT_CARD",
    #     :amount=>5000,
    #     :creditCard=>{
    #       :brand=>"VISA",
    #       :panLastDigits=>"1855",
    #       :expirationMonth=>12,
    #       :expirationYear=>2020,
    #       :holderName=>"TESTE CONSOLE",
    #       :customer=>{
    #         :documentType=>"CPF",
    #         :documentNumber=>"41468031520"
    #       }
    #     },
    #     :token=>"a2bebd13f0a43e5a",
    #     :status=>"CANCELLED"
    #   }
    # }
    def subscription_by_token(subscription_token)
      # define o método de envio da requisição
      method = :get

      # monta a URL de chamada da requisição
      endpoint =  EndPoints.get_env[:url] + EndPoints.get_env[:context] + EndPoints::SUBSCRIPTIONS[:by_token].gsub('{subscriptionToken}', subscription_token)

      # faz a chamada a plataforma de pagamento (MIDAS)
      response = request(method, endpoint, self.login, self.password, {})

      return response[:result], response[:subscription]
    end

    # This method performs a query by a specific transaction.
    # This is a is synchronous operation, using method GET
    #
    # Params:
    #   subscription_token: string (Transaction unique identification generated by our
    #                             gateway and received in the subscription's create response)#
    #
    #
    # Response:
    #
    # {
    #   :result=>{
    #     :success=>true,
    #     :code=>"000",
    #     :message=>"Sucesso"
    #   },
    #   :invoices=>[{
    #     :number=>1,
    #     :amount=>5000,
    #     :expirationDate=>"2016-07-28",
    #     :token=>"8bc3bf2ff9b08566fa8496fdce6c6f99",
    #     :status=>"PAID"
    #   }. {:number=>2,...}, {:number=>3,}]
    # }
    def subscription_invoices(subscription_token)
      # define o método de envio da requisição
      method = :get

      # monta a URL de chamada da requisição
      endpoint =  EndPoints.get_env[:url] + EndPoints.get_env[:context] + EndPoints::SUBSCRIPTIONS[:invoices].gsub('{subscriptionToken}', subscription_token)

      # faz a chamada a plataforma de pagamento (MIDAS)
      response = request(method, endpoint, self.login, self.password, {})

      return response[:result], response[:invoices]
    end

    # This method updates the credit card information associated to the subscription.
    # This is a is synchronous operation, using method PUT
    #
    # Params:
    #   subscription_token: string (Transaction unique identification generated by our
    #                             gateway and received in the subscription's create response)#
    #   new_card_token: string that represents the new credit card token (created using card_store) for the subscription
    #
    # Response:
    # {
    #  "result": {
    #    "success": true,
    #    "code": "0",
    #    "message": "Sucesso"
    #  }
    # }
    #
    def update_subscription_card(subscription_token, new_card_token)
      # define o método de envio da requisição
      method = :put

      # monta a URL de chamada da requisição
      endpoint =  EndPoints.get_env[:url] + EndPoints.get_env[:context] + EndPoints::SUBSCRIPTIONS[:update_card].gsub('{subscriptionToken}', subscription_token)

      params = {
          cardToken: new_card_token
      }

      # faz a chamada a plataforma de pagamento (MIDAS)
      response = request(method, endpoint, self.login, self.password, params)

      response[:result]
    end

    # This method updates a subscription.
    # This is a is synchronous operation.
    #
    # Params:
    #   subscriptionToken: querystring (Subscription unique identification generated by our
    #                             gateway and received in the subscription's creation response)
    #   amount: number (Only integer numbers, with the last two digits representing the cents.
    #                   For example: 100 is equivalent to R$ 1,00)
    #   expirationDate string deadline date for the invoice. FORMAT: YYY-MM-DD
    #
    # Response:
    #   result: {
    #     success: true/false
    #     code: "XXX"
    #     message: "Some message to you"
    #   }
    def update_invoice(invoice_token, params)
      # define o método de envio da requisição
      method = :put

      # monta a URL de chamada da requisição
      endpoint =  EndPoints.get_env[:url] + EndPoints.get_env[:context] + EndPoints::SUBSCRIPTIONS[:update_invoice].gsub('{invoiceToken}', invoice_token)

      # faz a chamada a plataforma de pagamento (MIDAS)
      response = request(method, endpoint, self.login, self.password, params)

      response[:result]
    end

  end

end