<?php

namespace Edoobox\Requests;

use Edoobox\Base\BaseController;
use Edoobox\Base\Options;
use Edoobox\Helpers\Arr;
use Edoobox\Base\Cache;
use Edoobox\Base\Settings;
use Edoobox\Requests\Helpers\Request;
use Edoobox\Requests\Helpers\Shortcode;
use Exception;

class Template {
    public array $attributes;
    private Auth $auth;
    private Settings $settings;

    public function __construct($attributes) {
        $this->attributes = $attributes ?? Shortcode::$KNOWN_ATTRIBUTES;
        $this->auth = new Auth();
        $this->settings = new Settings();
    }

    public function fetch(): array {
        return $this->settings->get(Settings::USE_V2) ? $this->fetchV2() : $this->fetchV1();
    }

    public function fetchV1(): array {
        try {
            $query = $this->buildRequestQueryString();
            $baseUrl = BaseController::getApiBaseUrl();
            $url = $baseUrl . "/v1/templates$query";

            $cacheKey = Page::getCurrentPageCacheKey($this->attributes);
            $cache = Cache::get($cacheKey);
            if ($cache) {
                return $cache;
            }

            $apiData = wp_remote_get($url, ['timeout' => Settings::SETTINGS_REQUEST_TIMEOUT]);
            Request::checkResponse($apiData);
            $response = [
                'api' => json_decode($apiData['body'], true),
                'provider_url' => Request::buildProviderUrl(Arr::get($this->attributes, 'root', ''))
            ];

            Cache::set($cacheKey, $response, Options::get('edoobox_cache_time_in_s', 0));

            return $response;
        } catch ( Exception $exception ) {
            Request::renderException($exception);
            return [];
        }
    }

    public function fetchV2(): array {
        try {
            $this->auth->authenticate();
            $query = $this->buildRequestQueryString();
            $baseUrl = BaseController::getApiBaseUrl();
            $url = $baseUrl . "/v2/template$query";
            //xdebug_break();
            $cacheKey = Page::getCurrentPageCacheKey($this->attributes);
            $cache = Cache::get($cacheKey);
            if ($cache) {
                return $cache;
            }
            $apiData = wp_remote_get($url, [
                'headers' => [
                    "edid" => $this->auth->getEdid(),
                    "language" => $this->attributes["language"] ?? 'de',
                    "grant-type" => "access_token",
                    "Authorization" => "Bearer " . $this->auth->getAuthToken()
                ],
                'timeout' => Settings::SETTINGS_REQUEST_TIMEOUT
            ]);
            Request::checkResponse($apiData);
            $response = [
                'api' => json_decode($apiData['body'], true),
                'provider_url' => Request::buildProviderUrl($this->attributes['root'] ?? '')
            ];
            Cache::set($cacheKey, $response, Options::get('edoobox_cache_time_in_s', 0));
            return $response;
        } catch ( Exception $exception ) {
            Request::renderException($exception);
            return [];
        }
    }

    public function setDocumentTitle($title) {
        $uniqueKey = Page::getCurrentPageCacheKey($this->attributes);
        $cachedResponse = Cache::get($uniqueKey);

        if ( Arr::get($cachedResponse, 'api.data.header.title', false) ) {
            return Arr::get($cachedResponse, 'api.data.header.title');
        }

        $apiResponse = $this->fetch();

        Cache::set($uniqueKey, $apiResponse, Options::get('edoobox_cache_time_in_s', 0));

        return Arr::get($apiResponse, 'api.data.header.title', $title);
    }


    private function buildRequestQueryString(): string {
        $allowedQueries = ['edcode', 'edref', 'edtag', 'edpromo', 'edlanguage', 'edlink', 'edstart', 'edend', 'edview', 'q', 'edfilter'];
        $requestQueries = [];

        foreach ($allowedQueries as $query) {
            $queryValue = get_query_var($query);
            $valueIsEmpty = $queryValue === '' || $queryValue === null;

            if (!$valueIsEmpty) {
                $requestQueries[$query] = $queryValue;
                continue;
            }

            if ($query === 'q' && ($this->attributes['q'] ?? '') !== '') {
                $requestQueries['q'] = $queryValue;
                continue;
            }

            if (array_key_exists((string)substr($query, 2), $this->attributes) && $this->attributes[substr($query, 2)] !== '') {
                $requestQueries[$query] = $this->attributes[substr($query, 2)] ?? '';
                continue;
            }

            if ($query == 'edref' && ($this->attributes['label'] ?? '') !== '') {
                $requestQueries[$query] = $this->attributes['label'] ?? '';
            }
        }

        if ($this->settings->get(Settings::USE_V2)) {
            $requestQueries['filter'] = json_encode([
                [
                    'property' => 'template.path',
                    'value' => $this->buildTemplatePath()
                ],
                [
                    'property' => 'provider.url',
                    'value' => Request::buildProviderUrl($this->attributes['root'] ?? '')
                ]
            ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        } else {
            $requestQueries['cms_data'] = json_encode($this->buildRequestData(), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        }

        $queryString = '';
        foreach ($requestQueries as $key => $value) {
            $queryString .= $key . '=' . $value . '&';
        }

        $finalQueryString = '?' . rtrim($queryString, '&');

        return mb_convert_encoding($finalQueryString, 'UTF-8', 'auto');
    }

    private function buildRequestData(): array {
        return [
            "api1" => $this->auth->getPublicKey(),
            "api2" => $this->auth->getSecretKey(),
            "language" => Arr::get($this->attributes, 'language', 'de'),
            "filter" => [[
                'property' => 'template.path',
                'value' => $this->buildTemplatePath()
            ]],
            "data" => [[
                'property' => 'provider.url',
                'value' => Request::buildProviderUrl(Arr::get($this->attributes, 'root', ''))
            ]]
        ];
    }

    private function buildTemplatePath() {
        global $wp_query;

        if ( isset($wp_query->query_vars['ed_url']) && $wp_query->query_vars['ed_url'] ) {
            return $this->settings->get('account_code') . '/' . $wp_query->query_vars['ed_url'];
        }

        if ( ! ($this->attributes['url'] ?? '') ) {
            return $this->settings->get('account_code');
        }

        return $this->attributes['url'] ?? '';
    }
}