<?php

class Pagarme extends RestApi
{
  const urlPagarme = 'https://api.pagar.me/core/v5';

  private $header;
  private $basicAuthUserName = '';
  private $basicAuthPassword = '';
  public $registry;
  public $load;
  public $log;
  public $config;
  public $session;
  public $request;
  public $db;
  public $url;

  public function __construct($registry)
  {
    $this->registry = $registry;
    $this->load = $registry->get('load');
    $this->log = $registry->get('log');
    $this->config = $registry->get('config');
    $this->session = $registry->get('session');
    $this->request = $registry->get('request');
    $this->db = $registry->get('db');
    $this->log = $registry->get('log');
    $this->url = $registry->get('url');
    $this->basicAuthUserName = $this->config->get('pagarme_client_secret');
  }

  public function getAccessToken()
  {
    $client = new PagarmeCoreApiLib\PagarmeCoreApiClient(Crypto::descriptografarAES256($this->basicAuthUserName, Crypto::CAES256), $this->basicAuthPassword);
    return $client;
  }

  public function sendPaymentBillet($paymentData, $paymentInfo){

    $url = self::urlPagarme.'/orders';

    $header = [
      'Content-type: application/json; charset=utf-8',
      'Authorization: Basic '. base64_encode(Crypto::descriptografarAES256($this->basicAuthUserName, Crypto::CAES256).':'.'TODO: Replace'),
      'Cache-Control: no-cache'
    ];

    $client = $this->getAccessToken();
    $order = $this->createOrder($paymentData,$paymentInfo,$client,'boleto');

    $data = parent::callAPI($url, 'POST', $order, $header, false, $retorno, Type_DadosSend::TpDados_Json);

    if($data){
      switch ($retorno) {
        case '500':
        case '200':
        case '201':
          return $data;
          break;
        default :
          $error = 'Erro no módulo de pagamento';
          $error .= 'Mensagem: Erro na conexão com o Pagarme';
          throw new exception($error);
      }
    } else {
      $msgError = 'Erro ao finalizar o pedido usando Pagarme Boleto. Erro da API: ' . $data->message;
      $this->setErrorLog($msgError, $data);
      throw new exception($msgError);
    }
  }

  public function sendPaymentPix($paymentData, $paymentInfo){

    $client = $this->getAccessToken();
    $order = $this->createOrder($paymentData,$paymentInfo,$client,'Pix');

    $url = self::urlPagarme.'/orders';

    $header = [
      'Content-type: application/json; charset=utf-8',
      'Authorization: Basic '. base64_encode(Crypto::descriptografarAES256($this->basicAuthUserName, Crypto::CAES256).':'.'TODO: Replace'),
      'Cache-Control: no-cache'
    ];

    $data = parent::callAPI($url, 'POST', $order, $header, false, $retorno, Type_DadosSend::TpDados_Json);

    if($data){
      switch ($retorno) {
        case '500':
        case '200':
        case '201':
          return $data;
          break;
        default :
          $error = 'Erro no módulo de pagamento';
          $error .= 'Mensagem: Erro na conexão com o Pagarme';
          throw new exception($error);
      }
    } else {
      $msgError = 'Erro ao finalizar o pedido usando Pagarme Pix. Erro da API: ' . $data->message;
      $this->setErrorLog($msgError, $data);
      throw new exception($msgError);
    }
  }

  protected function setErrorLog($msgError, $data){
    if (isset($data->details)){
      $this->log->write($msgError.PHP_EOL.print_r($data->details,true));
    }
  }

  public function sendPaymentCreditCard($paymentData, $paymentInfo)
  {
    $url = self::urlPagarme.'/orders';

    $header = [
      'Content-type: application/json; charset=utf-8',
      'Authorization: Basic '. base64_encode(Crypto::descriptografarAES256($this->basicAuthUserName, Crypto::CAES256).':'.'TODO: Replace'),
      'Cache-Control: no-cache'
    ];

    $client = $this->getAccessToken();
    $order = $this->createOrder($paymentData,$paymentInfo,$client,'credit_card');

    $data = parent::callAPI($url, 'POST', $order, $header, false, $retorno, Type_DadosSend::TpDados_Json);

    if($data){
      switch ($retorno) {
        case '500':
        case '200':
        case '201':
          return $data;
          break;
        default :
          $error = 'Erro no módulo de pagamento';
          $error .= 'Mensagem: Erro na conexão com o Pagarme';
          throw new exception($error);
      }
    } else {
      $msgError = 'Erro ao finalizar o pedido usando Pagarme Cartão de Credito. Erro da API: ' . $data->message;
      $this->setErrorLog($msgError, $data);
      throw new exception($msgError);
    }

  }

  private function createOrder($paymentData, $paymentInfo, $client, $method){
    $order = new PagarmeCoreApiLib\Models\CreateOrderRequest();

    $pagarme_address  = new PagarmeCoreApiLib\Models\CreateAddressRequest();

    $adress = $paymentData['credit_card']['customer']['billing_address'];

    $this->load->dmodel('localisation/country');
    $country_info = $this->load->dmodel_localisation_country->getCountry(Type_PaisId::Tp_Brasil);

    $pagarme_address->street        = $adress['street'];
    $pagarme_address->number        = $adress['number'];
    $pagarme_address->zipCode       = $adress['postal_code'];
    $pagarme_address->city          = $adress['city'];
    $pagarme_address->state         = $adress['state'];
    $pagarme_address->country       = $country_info['iso_code_2'];
    $pagarme_address->complement    = $adress['complement'];
    $pagarme_address->line1         = $adress['number'] .','. $adress['street'] .','. $adress['district'];
    $pagarme_address->line2 = null;

    $pagarme_phones   = new PagarmeCoreApiLib\Models\CreatePhonesRequest();
    $pagarme_homephone   = new PagarmeCoreApiLib\Models\CreatePhoneRequest();

    $pagarme_homephone->areaCode    = $paymentInfo->getTelefone()->ddd;
    $pagarme_homephone->countryCode = Type_CountryCode::Tp_Brazil;
    $pagarme_homephone->number      = $paymentInfo->getTelefone()->completo;

    $pagarme_phones->homePhone   = $pagarme_homephone;

    $pagarme_customer = new PagarmeCoreApiLib\Models\CreateCustomerRequest();

    $pagarme_customer->name     = $paymentData['credit_card']['customer']['first_name'];
    $pagarme_customer->email    = $paymentData['credit_card']['customer']['email'];
    $pagarme_customer->document = $paymentData['credit_card']['customer']['document_number'];
    $pagarme_customer->type     = $paymentData['credit_card']['customer']['document_type'] == 'CPF'? 'individual':'company';
    $pagarme_customer->address  = $pagarme_address;
    $pagarme_customer->phones   = $pagarme_phones;
    $pagarme_customer->code     = $paymentData['credit_card']['customer']['customer_id'];
    $pagarme_customer->gender   = $paymentData['credit_card']['customer']['gender'] == 'm'? 'male' : 'female';
    $pagarme_customer->documentType = $paymentData['credit_card']['customer']['document_type'];

    $order->customer  = $pagarme_customer;
    $order->code =  $paymentData['credit_card']['order']['order_id'];
    $array_items = [];
    foreach ($paymentInfo->getProducts() as $products){
      $pagarme_Item = new PagarmeCoreApiLib\Models\CreateOrderItemRequest();

      $pagarme_Item->code         = $products->getId();
      $pagarme_Item->amount       = str_replace('.','',number_format($products->getPrice(),2));
      $pagarme_Item->category     = $products->getModel();
      $pagarme_Item->description  = $products->getDescricao();
      $pagarme_Item->quantity     = $products->getQuantity();

      array_push($array_items,$pagarme_Item);
    }

    $order->items = $array_items;

    //shipping
    $pagarme_shipping = new PagarmeCoreApiLib\Models\CreateShippingRequest();
    $pagarme_address = new PagarmeCoreApiLib\Models\CreateAddressRequest();

    $shipping_address = $paymentData['credit_card']['shippings'][0]['address'];

    $pagarme_address->street  = $shipping_address['street'];
    $pagarme_address->country = $country_info['iso_code_2'];
    $pagarme_address->state   = $shipping_address['state'];
    $pagarme_address->city    = $shipping_address['city'];
    $pagarme_address->zipCode = $shipping_address['postal_code'];
    $pagarme_address->line1   = $shipping_address['number'] .','. $shipping_address['street'] .','. $shipping_address['district'];
    $pagarme_address->line2   = $shipping_address['complement'];

    $pagarme_shipping->amount = str_replace('.','',$paymentInfo->getFrete()) / 100;
    $pagarme_shipping->description = $paymentInfo->getParam('shipping_method');
    $pagarme_shipping->recipientName = $paymentInfo->getNome();
    $pagarme_shipping->recipientPhone = $paymentInfo->getTelefone()->completo;
    $pagarme_shipping->address = $pagarme_address;

    $order->shipping = $pagarme_shipping;
    $method_payment = [];

    switch ($method){
      case 'credit_card': $method_payment = $this->paymentCreditCard($paymentData, $paymentInfo, $client, $pagarme_address);break;
      case 'boleto'     : $method_payment = $this->paymentBillet($paymentData, $paymentInfo, $client, $pagarme_address);break;
      case 'Pix'        : $method_payment = $this->paymentPix($paymentData, $paymentInfo, $client, $pagarme_address);break;
    }

    //Payments
    $pagarme_payments = new PagarmeCoreApiLib\Models\CreatePaymentRequest();

    $payments = [];
    $pagarme_payments->paymentMethod = $method;

    $pagarme_payments->amount = $paymentData['credit_card']['amount'];

    switch ($method){
      case 'credit_card': $pagarme_payments->creditCard = $method_payment ; break;
      case 'boleto'     : $pagarme_payments->boleto = $method_payment     ; break;
      case 'Pix'        : $pagarme_payments->pix = $method_payment        ; break;
    }

    array_push($payments, $pagarme_payments);

    $order->payments = $payments;

    $order->closed = true;            //Informa se o pedido será criado aberto ou fechado.

    $order->ip = $paymentData['credit_card']['device']['ip_address'];                //Endereço IP do dispositivo que solicitou a compra
    $order->sessionId = $paymentData['credit_card']['device']['device_id'];          //Código da sessão do usuário

    $order->antifraudEnabled = true;

    return $order;
  }

  private function paymentBillet($paymentData, $paymentInfo, $client, $pagarme_address){
    $pagarme_billet = new PagarmeCoreApiLib\Models\CreateBoletoPaymentRequest();

    $pagarme_billet->bank         = $this->config->get('pagarme_bank');
    $pagarme_billet->instructions = $this->config->get('pagarme_instrucao');
    $pagarme_billet->nossoNumero  = $paymentData['billet']['order']['order_id'];
    $pagarme_billet->dueAt        = $paymentData['billet']['boleto']['expiration_date'];

    return $pagarme_billet;

  }

  private function paymentPix($paymentData, $paymentInfo, $client, $pagarme_address){
    $pagarme_pix = new PagarmeCoreApiLib\Models\CreatePixPaymentRequest();
    $pagarme_info = new PagarmeCoreApiLib\Models\PixAdditionalInformation();

    $info = [];

    $pagarme_info->name  = 'Valor';
    $pagarme_info->value = $paymentData['billet']["amount"];
    array_push($info,$pagarme_info);

    $pagarme_info->name  = 'Loja';
    $pagarme_info->value = $this->config->get('config_name');
    array_push($info,$pagarme_info);

    $pagarme_info->name  = 'CNPJ';
    $pagarme_info->value = $this->config->get('config_cnpj');
    array_push($info,$pagarme_info);

    $pagarme_pix->expiresAt    = $paymentData['pix']['informations']['expiration_date'];
    $pagarme_pix->additionalInformation = $info;

    return $pagarme_pix;

  }

  private function paymentCreditCard($paymentData, $paymentInfo, $client, $pagarme_address){

    $pagarme_credit_card = new PagarmeCoreApiLib\Models\CreateCreditCardPaymentRequest();
    $pagarme_card = new PagarmeCoreApiLib\Models\CreateCardRequest();

    $credit_card = $paymentInfo->getCreditCard();

    $pagarme_card->number = $credit_card->getNumero();
    $pagarme_card->holderName = $credit_card->getNome();
    $pagarme_card->expMonth = $credit_card->getDataExp()->mes;
    $pagarme_card->expYear  = $credit_card->getDataExp()->ano;
    $pagarme_card->cvv = $credit_card->getCodigo();
    $pagarme_card->brand = $credit_card->getBandeira();
    $pagarme_card->billingAddress = $pagarme_address;

    $tokenize = $client->getTokens();

    $pagarme_token = new PagarmeCoreApiLib\Models\CreateTokenRequest();

    $pagarme_token->card = $pagarme_card;

    $token = $tokenize->createToken(Crypto::descriptografarAES256($this->config->get('pagarme_client_public'), Crypto::CAES256),$pagarme_token);

    $pagarme_credit_card->cardToken = $token->id;
    $pagarme_credit_card->card = $pagarme_card;

    $pagarme_credit_card->operationType = 'auth_and_capture';
    $pagarme_credit_card->installments = $credit_card->getParcelas();
    $pagarme_credit_card->statementDescriptor = $this->config->get('pagarme_statement_descriptor') ? $this->config->get('pagarme_statement_descriptor') : null;

    return $pagarme_credit_card;
  }
}