module MidasClient

  class Subscription < Request

    #= 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
      if params[:cardToken].blank?
        endpoint=  get_env[:url] + EndPoints::SUBSCRIPTIONS[:context] + EndPoints::SUBSCRIPTIONS[:create_manual]
      else
        endpoint=  get_env[:url] + EndPoints::SUBSCRIPTIONS[:context] + EndPoints::SUBSCRIPTIONS[:create_recurrent]
      end

      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)
      request(method, endpoint, self.login, self.password, params)
    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/falseb0FIYhr/xCvGFMuR1Wg059X/0cqwLg==
    #     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 =  get_env[:url] + EndPoints::SUBSCRIPTIONS[:context] + EndPoints::SUBSCRIPTIONS[:cancel].gsub('{subscriptionToken}', subscription_token)

      # faz a chamada a plataforma de pagamento (MIDAS)
      request(method, endpoint, self.login, self.password, {})
    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)
    #   params: {
    #             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 =  get_env[:url] + EndPoints::SUBSCRIPTIONS[: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.
      response_invoices = subscription_invoices(subscription_token)
      result = response_invoices[:result]
      invoices = response_invoices[:invoices]

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

      # 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 unless opened_invoices.blank?
      response
    end

    #= This method renew a subscription increasing the number of invoices associated. Works as a most complete update_subscription operation.
    # This is a is synchronous operation.
    #
    # Params:
    #   subscriptionToken: URL querystring
    #   body:
    #   {
    #     "invoicesCount":2,
    #     "amount":200,
    #     "expirationDate":"2019-01-01"
    #   }
    #
    # Response:
    #   result: {
    #     success: true/false
    #     code: "XXX"
    #     message: "Some message to you"
    #   }
    def renew_subscription(subscription_token, params)
      # define o método de envio da requisição
      method = :put

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

      # faz a chamada a plataforma de pagamento (MIDAS) para atualizar o valor, numero de invoices e data de expiração inicial das novas invoices de uma assinatura.
      response = request(method, endpoint, self.login, self.password, params)

      response
    end

    #= This method performs a query by a specific subscription.
    # 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 =  get_env[:url] + EndPoints::SUBSCRIPTIONS[:context] + EndPoints::SUBSCRIPTIONS[:by_token].gsub('{subscriptionToken}', subscription_token)

      # faz a chamada a plataforma de pagamento (MIDAS)
      request(method, endpoint, self.login, self.password, {})
    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 =  get_env[:url] + EndPoints::SUBSCRIPTIONS[:context] + EndPoints::SUBSCRIPTIONS[:invoices].gsub('{subscriptionToken}', subscription_token)

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

    #= This method performs a query by a invoice token and return all transactions associated to it.
    # This is a is synchronous operation, using method GET
    #
    # Params:
    #   invoice_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"
    #   },
    #   "transactions": [
    #    {
    #        "externalDate": "2017-10-13T03:00:00.731",
    #        "transactionType": "RECURRENT",
    #        "paymentMethod": "CREDIT_CARD",
    #        "creditCard": {
    #            "brand": "MASTER",
    #            "panLastDigits": "1137",
    #            "expirationMonth": 1,
    #            "expirationYear": 2022,
    #            "holderName": "Fulano de Tals",
    #            "customer": {
    #                "documentType": "CPF",
    #                "documentNumber": "24503795710"
    #            }
    #        },
    #        "amount": 22950,
    #        "instalments": 1,
    #        "token": "3962f882146ec3f6bf581a883f52004f",
    #        "status": "ERROR"
    #    }
    #   ]
    # }
    def invoice_transactions(invoice_token)
      # define o método de envio da requisição
      method = :get

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

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

    #= This method associate a transactionToken to an invoice, which changes the invoice status
    # This is a is synchronous operation, using method PUT
    #
    # Params:
    #   invoice_token: string (Transaction unique identification generated by our
    #                             gateway and received in the subscription's create response)#
    #
    #   transaction_token: string Identification of the token from the transaction that will
    #                             be associated to the invoice
    #
    # Response:
    #
    # {
    #   :result=>{
    #     :success=>true,
    #     :code=>"000",
    #     :message=>"Sucesso"
    # }
    def invoice_payment(invoice_token, transaction_token)
      # define o método de envio da requisição
      method = :put

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

      # faz a chamada a plataforma de pagamento (MIDAS)
      request(method, endpoint, self.login, self.password, {transactionToken: transaction_token})
    end

    #= This method set an invoice as PAID, which changes the invoice status
    # This is a is synchronous operation, using method PUT
    #
    # Params:
    #   payment_date: string (format YYYY-MM-DD, ex: 2018-05-28)
    #
    #   payment_voucher: string Identification of the external payment that will
    #                             be associated to the invoice
    #
    # Response:
    #
    # {
    #   :result=>{
    #     :success=>true,
    #     :code=>"000",
    #     :message=>"Sucesso"
    # }
    def invoice_external_payment(invoice_token, payment_date, payment_voucher)
      # define o método de envio da requisição
      method = :put

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

      # faz a chamada a plataforma de pagamento (MIDAS)
      request(method, endpoint, self.login, self.password, {paymentDate: payment_date, paymentVoucher: payment_voucher})
    end

    #= This method cancel an invoice of a subscription
    # This is a is synchronous operation, using method PUT
    #
    # Params:
    #   invoice_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"
    # }
    def invoice_cancel(invoice_token)
      # define o método de envio da requisição
      method = :put

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

      # faz a chamada a plataforma de pagamento (MIDAS)
      request(method, endpoint, self.login, self.password, {})
    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 =  get_env[:url] + EndPoints::SUBSCRIPTIONS[:context] + EndPoints::SUBSCRIPTIONS[:update_card].gsub('{subscriptionToken}', subscription_token)

      params = {
          cardToken: new_card_token
      }

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

    #= This method updates a subscription.
    # This is a is synchronous operation.
    # QueryString:
    #   invoice_token: Invoice unique identification generated by our gateway
    # Params:
    #   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: YYYY-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 =  get_env[:url] + EndPoints::SUBSCRIPTIONS[:context] + EndPoints::SUBSCRIPTIONS[:update_invoice].gsub('{invoiceToken}', invoice_token)

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

  end

end