<?php
namespace Datacake\Core\Wda;

use GuzzleHttp\Psr7\Request;
use Http\Adapter\Guzzle6\Client;
use WoohooLabs\Yang\JsonApi\Request\JsonApiRequestBuilder;
use WoohooLabs\Yang\JsonApi\Client\JsonApiClient;

class BaseApi {
    public $request;
    private $_requestBuilder = null;
    public $config;
    public $baseUrl;
    public $version = 'api/v1';
    public $type;
    public $client;
    public $token;
    public $raiseError = false;
    public function __construct($args = array()) {
        if(isset($args['raiseError']) && $args['raiseError'] == true){
            $this->raiseError = true;
        }
        // Instantiate the Guzzle HTTP Client
        $this->client = new JsonApiClient(
            Client::createWithConfig(
                [
                    'verify' => false,
                ]
            )
        );

        $this->config = get_option('datacake_api');
        // Instantiate an empty PSR-7 request, note that the default HTTP method must be provided
        $this->request = new Request('GET', '');

        
    }
    public function getRequestBuilder() {
        // Instantiate the request builder
        if($this->_requestBuilder){
            return $this->_requestBuilder;
        }
        $this->_requestBuilder = new JsonApiRequestBuilder($this->request);
        
        if($this->config){
            $this->_requestBuilder
                ->setProtocolVersion("1.1")
                ->setMethod("GET")
                ->setUri($this->generateBaseUri())
                ->setHeader("Accept-Charset", "utf-8");
            try {
                $token = $this->getToken();
                if($token){
                    $this->_requestBuilder
                    ->setHeader("Authorization", "Bearer ".$token);
                }
            } catch (\Throwable $th) {
                //throw $th;
                if($this->raiseError){
                    throw $th;
                }
                
            }
            
        }
        return $this->_requestBuilder;
    }
    public function getToken(){
        $token = get_transient('datacake_api_token');
        if($token){
            return $token;
        } 
        if($this->config['url'] && $this->config['password'] && $this->config['email']){
            $headers = [
                "Accept-Charset" => "utf-8",
                "Content-Type" => "application/vnd.api+json",
                "Accept-Type" => "application/vnd.api+json"
            ];
            $request = new Request('POST', $this->config['url']."api/token/",$headers, json_encode([
                "username_or_email"=> $this->config['email'],
                "password"=> $this->config['password']
            ]));
            
            $response = $this->client->sendRequest($request);
            if($response->getStatusCode() < 400){
                $body = $response->getBody()->__toString();
                $token = json_decode($body);
                $token = $token->data->token;
                // Set token for a day
                set_transient('datacake_api_token',$token,86400);
            
                return $token;
            }else{
                delete_transient('datacake_api_token');
                if($this->raiseError){
                    throw new \Exception($this->treatError($response), $response->getStatusCode());
                }
                
            }
        }
        return null;
    }
    public function treatError($response) {
        
        $data = json_decode($response->getBody()->__toString(), true);
        $message = "Api Error: ";
        if(isset($data['errors'])){
            foreach ($data['errors'] as $key => $value) {
                $e = "";
                if(is_array($value)){
                    foreach ($value as $k => $v) {
                        $e .= $v;
                    }
                }else{
                    $e = $value;
                }
                $message .= $key.": $e";
            }
        }else{
            $message .= $response->getBody()->__toString();
        }
        return $message;
    }
    private function generateBaseUri(){
        return $this->config['url'].$this->version.$this->baseUrl;
    }
    public function setUrl($url = ''){
        $this->getRequestBuilder()->setUri($this->config['url'].$this->version.$url);
    }
    public function setJsonApiFilter($filters){
        $this->getRequestBuilder()->setJsonApiFilter($filters);
        return $this;
    }
    public function setJsonApiFields($fields){
        if(is_array($fields)){
            $fields = implode("," , $fields);
            $fields = trim($fields,",");
        };
        $this->getRequestBuilder()->setUriQueryParam('fields',$fields);
        return $this;
    }
    public function get($id){
        $this->getRequestBuilder()->setUri($this->generateBaseUri()."$id/");
        $request = $this->getRequestBuilder()->getRequest();
        $response =  $this->client->sendRequest($request);
        // returning base URI
        $this->getRequestBuilder()->setUri($this->generateBaseUri());
        return $response;
    }
    public function setJsonApiInclude($include){
        if(is_array($include)){
            $include = implode("," , $include);
            $include = trim($include,",");
        };
        $this->getRequestBuilder()->setUriQueryParam('include',$include);
        return $this;
    }
    public function setJsonApiPage($page = ["number" => 1, "size" => 100]){
        $this->getRequestBuilder()->setJsonApiPage($page);
        return $this;
    }
    public function getRequest(){
        return $this->getRequestBuilder()->getRequest();
    }
    public function list(){
        
        $request = $this->getRequestBuilder()->getRequest();
        
        return $this->client->sendRequest($request);
        
    }
}