module MidasClient
    class Transaction < Request

      include EndPoints

      # This method securely stores credit card's data (pan, expiration...)
      # and returns a token to be used to perform payment transactions.
      #
      # Params:
      #   externalId: number (Transaction identification on the client application)
      #   pan: number
      #   expirationMonth: number (format: MM)
      #   expirationYear: number (format: YYYY)
      #   holderName: string
      #   customer/documentType: string (values: {'CPF', 'CNPJ'})
      #   customer/documentNumber: string
      #
      # Response success:
      #  {
      #    "result": {
      #      "success":"true",
      #      "code":"000",
      #      "message":"Success"
      #    },
      #    "brand":"VISA",
      #    "cardToken":"2b5141a2209384e4266c8f7cbaf67a2d"
      #  }
      #
      # Response Failure
      # {
      #   :result=>{
      #     :success=>false,
      #     :code=>"120",
      #     :message=>"O numero do documento eh obrigatorio"
      #   }
      # }
      #
      def card_store(*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::OPERATIONS[:context] + EndPoints::OPERATIONS[:store]

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

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

      # This method creates a payment transaction, already performing
      # the authorization and capture in only one step.
      #
      # Params:
      #   externalId: string (Transaction identification on the client application)
      #   externalDate: Date and time form client application - YYYY-MM-DDThh:mm:SS.sssTDZ - ISO8601
      #   cardToken: string (created by method card_store)
      #   cvv: number (Security Code)
      #   amount: number (Only integer numbers, with the last two digits representing the cents.
      #                   For example: 100 is equivalent to R$ 1,00)
      #   instalments: number (1 to 12)
      #
      # Response:
      #   result: {
      #     success: true/false
      #     code: "XXX"
      #     message: "Some message to you"
      #   },
      #   transactionToken: "65ffe2897b832cb89cb2063b74fbb143",
      #   nsu: "99999"
      #
      def synchronous_transaction(*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::OPERATIONS[:context] + EndPoints::OPERATIONS[:synchronous_transaction]

        # regulariza o formato da data
        params[:externalDate] = params[:externalDate].blank? ? Time.now.iso8601(1) : params[:externalDate]

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

        return response[:result], response[:transactionToken], response[:nsu]
      end

      # This method dispatches a payment transaction creation request, already performing
      # the authorization and capture in only one step, but sending the response using the
      # informed callback URL, in an asynchronous away.
      #
      # Params:
      #   externalId: string (Transaction identification on the client application)
      #   externalDate: Date and time form client application - YYYY-MM-DDThh:mm:SS.sssTDZ - ISO8601
      #   cardToken: string (created by method card_store)
      #   cvv: number (Security Code)
      #   softDescriptor: string (Text to be shown on the credit card invoice entry)
      #   amount: number (Only integer numbers, with the last two digits representing the cents.
      #                   For example: 100 is equivalent to R$ 1,00)
      #   instalments: number (1 to 12)
      #   callbackUrl: string (URL used to notify the client application about the transaction creation result. )
      #
      # # Response:
      #   result: {
      #     success: true/false
      #     code: "XXX"
      #     message: "Some message to you"
      #   },
      #   transactionToken: "65ffe2897b832cb89cb2063b74fbb143",
      #
      def asynchronous_transaction(*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::OPERATIONS[:context] + EndPoints::OPERATIONS[:asynchronous_transaction]

        # regulariza o formato da data
        params[:externalDate] = (params[:externalDate].blank? ? Time.now.iso8601(1) : params[:externalDate])

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

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

      # This method dispatches a debit payment transaction request, that's receive an authorization URL,
      # where the payer must authorize the transaction.
      #
      # Params:
      #   externalId: string (Transaction identification on the client application)
      #   externalDate: Date and time form client application - YYYY-MM-DDThh:mm:SS.sssTDZ - ISO8601
      #   pan: DebitCard Number
      #   expirationMonth:
      #   expirationYear:
      #   holderName:
      #   customer/documentType: CPF/CNPJ
      #   customer/documentNumber: if CPF 11 digits else CNPJ 13 digits
      #   cvv: number (Security Code)
      #   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 used to notify the client application about the transaction authorization result. async notification )
      #   redirectUrl: string (URL used to notify the client application that the transaction authorization result successful. )
      #   errorUrl: string (URL used to notify the client application that the transaction authorization result failed)
      #
      # # Response:
      #   result: {
      #     success: true/false
      #     code: "XXX"
      #     message: "Some message to you"
      #   },
      #   "authenticationUrl": "https://qasecommerce.cielo.com.br/web/index.cbmp?id=ac470d041f660e21d253a5741e59c5b4",
      #   "transactionToken":"6accbedb2da4f7bfbca5b5fed3669be6",
      #
      def asynchronous_debit_transaction(*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::OPERATIONS[:context] + EndPoints::OPERATIONS[:asynchronous_debit_transaction]

        # regulariza formato da data
        params[:externalDate] = (params[:externalDate].blank? ? Time.now.iso8601(1) : params[:externalDate])

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

        return response[:result], response[:authenticationUrl], response[:transactionToken]
      end

      # This method performs a payment authorization. This is a is synchronous operation.
      # To confirm the payment and finish the transaction you must send a capture request
      #
      # Params:
      #   externalId: string (Transaction identification on the client application)
      #   externalDate: Date and time form client application - YYYY-MM-DDThh:mm:SS.sssTDZ - ISO8601
      #   cardToken: string (created by method card_store)
      #   cvv: number (Security Code)
      #   amount: number (Only integer numbers, with the last two digits representing the cents.
      #                   For example: 100 is equivalent to R$ 1,00)
      #   instalments: number (1 to 12)
      #
      # Response:
      # {
      #   result: {
      #     success: true/false
      #     code: "XXX"
      #     message: "Some message to you"
      #   }
      # }
      #
      # Response Failure
      # {
      #   :result=>{
      #     :success=>false,
      #     :code=>"150",
      #     :message=>"A data externa é obrigatória"
      #   }
      # }
      #
      def authorize(*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::OPERATIONS[:context] + EndPoints::OPERATIONS[:authorize]

        # regulariza o formato da data
        params[:externalDate] = (params[:externalDate].blank? ? Time.now.iso8601(1) : params[:externalDate])

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

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

      # This method performs a capture (confirmation) in a already authorized transaction.
      # This is a is synchronous operation.
      #
      # Params:
      #   transactionToken: string (Transaction unique identification generated by our
      #                             gateway and received in the transaction authorization response)
      #
      # Response:
      #   result: {
      #     success: true/false
      #     code: "XXX"
      #     message: "Some message to you"
      #   }
      def capture(transaction_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::OPERATIONS[:context] + EndPoints::OPERATIONS[:confirm].gsub('{transactionToken}', transaction_token)

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

        response[:result]
      end

      # This method performs a cancellation in a already authorized transaction.
      # This is a is synchronous operation.
      #
      # Params:
      #   transactionToken: string (Transaction unique identification generated by our
      #                             gateway and received in the transaction authorization response)
      #
      # Response:
      #   result: {
      #     success: true/false
      #     code: "XXX"
      #     message: "Some message to you"
      #   }
      def cancellation(transaction_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::OPERATIONS[:context] + EndPoints::OPERATIONS[:cancel].gsub('{transactionToken}', transaction_token)

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

        response[:result]
      end

      # This method performs a refund in a captured authorized transaction.
      # This is a is synchronous operation.
      #
      # Params:
      #   transactionToken: string (Transaction unique identification generated by our
      #                             gateway and received in the transaction authorization response)#
      #
      #
      # Response:
      #   result: {
      #     success: true/false
      #     code: "XXX"
      #     message: "Some message to you"
      #   }
      def refund(transaction_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::OPERATIONS[:context] + EndPoints::OPERATIONS[:refund].gsub('{transactionToken}', transaction_token)

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

        response[:result]
      end

      # This method performs a query by a specific transaction.
      # This is a is synchronous operation, using method GET
      #
      # Params:
      #   transactionToken: string (Transaction unique identification generated by our
      #                             gateway and received in the transaction authorization response)#
      #
      #
      # Response:
      #   result: {
      #     success: true/false
      #     code: "XXX"
      #     message: "Some message to you"
      #   }
      def query_transaction(transaction_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::OPERATIONS[:context] + EndPoints::OPERATIONS[:query_by_transaction].gsub('{transactionToken}', transaction_token)

        response = request(method, endpoint, login, password, params)

        response[:result]
      end

      # This method performs a query by a specific transaction's identifier, called external ID.
      # This is a is synchronous operation, using method GET
      #
      # Params:
      #   transactionToken: string (Transaction unique identification generated by customer)
      #
      #
      # Response:
      #   result: {
      #     success: true/false
      #     code: "XXX"
      #     message: "Some message to you"
      #   }
      def query_external_id(externalId)
        # 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::OPERATIONS[:context] + EndPoints::OPERATIONS[:query_by_external_id].gsub('{externalId}', externalId)

        response = request(method, endpoint, login, password, params)

        response[:result]
      end

    end
end