<?php


class correiosUtils extends RestApi
{

  const urlApiTeste = 'https://apihomo.correios.com.br/';
  const urlApi = 'https://api.correios.com.br/';

  private $header;
  private $environment;
  private $accessToken = null;
  private $expiraEm = '';
  private $userAuth = '';
  private $passwordAuth = '';

  private $registry;

  public function __construct($registry) {
    $this->registry = $registry;

    $this->load = $registry->get('load');
    $this->config = $registry->get('config');
    $this->db = $registry->get('db');
    $this->log = $registry->get('log');
    $this->session = $registry->get('session');

    $this->userAuth = $this->config->get('correios_contrato_user');
    //TODO Correios Adicionar Criptografia em senhas
    $this->passwordAuth = $this->config->get('correios_contrato_senha');

    $this->accessToken = $this->config->get('correios_token');
    $this->expiraEm = $this->config->get('correios_expiraEm')??0;

    $this->setEnvironment();
    $this->setHeader();

  }

  public function setHeader()
  {
    $this->header = array(
      'Accept:application/json',
      'Content-Type: application/json',
      'Authorization: Bearer '.$this->accessToken
    );
  }
  public function getHeader()
  {
    return $this->header;
  }

  public function getAccessToken(){
    $url = $this->getEnvironment() .'token/v1/autentica/cartaopostagem';

    $basicAuth = base64_encode($this->config->get('correios_contrato_user') . ':' . $this->config->get('correios_contrato_senha'));
    
    $param = json_encode(array(
      "numero"=> $this->config->get('correios_postCartao')
    ));

    $header = array(
      'Accept: application/json;charset=UTF-8',
      'Content-Type: application/json',
      'Authorization: Basic '.$basicAuth
    );

    $data = $this->callAPI($url, 'POST', $param, $header, false, $httpcode);

    if ($this->error) {
      return $this->error;
    } else {
      if (is_object($data) && property_exists($data, 'token')) {
        $this->load->model('setting/setting');
        $expireTime = (new DateTime($data->expiraEm))->getTimestamp();

        $tokenInfo = array(
          'correios_token' => $data->token,
          'correios_expiraEm' => $expireTime,
        );


        $this->accessToken = trim($data->token);
        $this->expiraEm = $expireTime;

        $this->model_setting_setting->editSettingForKey('correios', $tokenInfo);
      }
      return $data;
    }
  }

  public function getAccess()
  {
    if(($this->config->get('correios_status') == Type_Status::Tp_Habilitado) and ($this->config->get('correios_api_status') == Type_Status::Tp_Habilitado)){

      if ((!$this->accessToken) || ($this->expiraEm < time() + 1)) {

        $refreshToken = $this->getAccessToken();
        if ($refreshToken === false){
          throw new exception($this->error);
        }

        $expireTime = (new DateTime($refreshToken->expiraEm))->getTimestamp();

        $this->accessToken = trim($refreshToken->token);
        $this->expiraEm = $expireTime;

        $this->setHeader();
      }
    }
  }

  public function gerServicosObrigatorios($codigo){
    $this->getAccess();

    $apiPath = $this->getEnvironment() .'preco/v1/servicos-adicionais/'.$codigo
      . '?sgPais=BR';

    $result = $this->callAPI($apiPath, 'GET', false, $this->getHeader(), false, $httpcode);

    switch ($httpcode){
      case 200:
      case 201:
      case 400:
        return $result;
        break;
      default: $this->log->write('Erro ao buscar CO: '. $codigo .'  '. print_r($this->error, true));
    }

  }

  public function getCorreiosPreco($data){
    $this->getAccess();
    
    $tokenParts = explode('.', $this->accessToken);
    $payload = (array)json_decode(base64_decode($tokenParts[1]));
  
    $dr = $payload['cartao-postagem']->dr; //Codigo do estado
    $contract = $payload['cartao-postagem']->contrato; //Numero do contrato com o correio
    $weightInGrams = str_replace(',','.',$data['psObjeto']) * 1000; // Converte para grama

    if($this->config->get('correios_declarar_valor') === "S" && $data['vlDeclarado'] > 0){
      $apiPath = $this->getEnvironment() .'preco/v1/nacional/'.$data['coProduto']
        . '?cepDestino='. $data['cepDestino']
        . '&cepOrigem='. $data['cepOrigem']
        . '&psObjeto='. $weightInGrams 
        . '&tpObjeto='. $data['tpObjeto']
        . '&comprimento='. str_replace(',','.',$data['comprimento'])
        . '&largura='. str_replace(',','.', $data['largura'])
        . '&altura='. str_replace(',','.', $data['altura'])
        . '&nuDR='. $dr
        . '&nuContrato='. $contract
        . ($data['servicosAdicionais'] != ''?'&servicosAdicionais='. $data['servicosAdicionais']: '')
        . '&vlDeclarado='. $data['vlDeclarado'];
    }else{
      $apiPath = $this->getEnvironment() .'preco/v1/nacional/'.$data['coProduto']
        . '?cepDestino='. $data['cepDestino']
        . '&cepOrigem='. $data['cepOrigem']
        . '&psObjeto='. $weightInGrams
        . '&tpObjeto='. $data['tpObjeto']
        . '&comprimento='. str_replace(',','.',$data['comprimento'])
        . '&largura='. str_replace(',','.', $data['largura'])
        . '&altura='. str_replace(',','.', $data['altura'])
        . '&nuDR='. $dr
        . '&nuContrato='. $contract;
    }

    $result = $this->callAPI($apiPath, 'GET', false, $this->getHeader(), false, $httpcode);

    switch ($httpcode){
      case 200:
      case 201:
        return $result;
        break;
      default: return $result;
    }
  }

  public function getCorreiosPrazo($sendData){
    $this->getAccess();

    $apiPath = $this->getEnvironment() .'prazo/v1/nacional';

    $data = $this->callAPI($apiPath, 'POST', json_encode($sendData), $this->getHeader(), false, $httpcode);

    switch ($httpcode){
      case 200:
      case 201:
      case 206:
      case 400:
          return $data;
        break;
      default: return $this->error;
    }
  }

  public function getTrackingObj($data){
    $this->getAccess();

    $apiPath = $this->getEnvironment() .'srorastro/v1/objetos/'. $data .'?resultado=T';

    $result = $this->callAPI($apiPath, 'GET', false, $this->getHeader(), false, $httpcode);

    if($result->objetos[0]->eventos){
      return $result;
    }

    return null;
  }

  public function getEnvironment()
  {
    return $this->environment;
  }

  public function setEnvironment()
  {
    //TODO CORREIOS verificar se precisa adicionar habiente de testes.
    $this->environment = self::urlApi;
  }

  public function __get($key) {
    return $this->registry->get($key);
  }

  public function __set($key, $value) {
    $this->registry->set($key, $value);
  }
}