<?php
/**
 * @package   Essentials YOOtheme Pro 2.2.16 build 0813.1608
 * @author    ZOOlanders https://www.zoolanders.com
 * @copyright Copyright (C) Joolanders, SL
 * @license   http://www.gnu.org/licenses/gpl.html GNU/GPL
 */

namespace ZOOlanders\YOOessentials\Api\Facebook;

use YOOtheme\Http\Response;
use ZOOlanders\YOOessentials\HttpClientInterface;
use ZOOlanders\YOOessentials\Auth\AuthOAuth;
use ZOOlanders\YOOessentials\Api\AbstractApi;
use ZOOlanders\YOOessentials\Vendor\Symfony\Contracts\Cache\CacheInterface;

class FacebookBaseApi extends AbstractApi
{
    protected ?string $accessToken = null;

    protected ?CacheInterface $cache = null;

    protected string $apiEndpoint = 'https://graph.facebook.com';

    public function __construct(CacheInterface $cache, HttpClientInterface $client)
    {
        parent::__construct($client);

        $this->cache = $cache;
    }

    public function forAccount(AuthOAuth $account): self
    {
        $this->accessToken = $account->accessToken();

        return $this;
    }

    public function withAccessToken(string $accessToken): AbstractApi
    {
        $this->accessToken = $accessToken;

        return $this;
    }

    public function me(): array
    {
        return $this->get('me');
    }

    public function debugToken(string $token): array
    {
        $this->withAccessToken($token);

        $result = $this->get('debug_token', [
            'input_token' => $token,
        ]);

        return $result['data'] ?? [];
    }

    protected function getUrl(string $name): string
    {
        if ($this->accessToken) {
            return parent::getUrl("{$name}?access_token={$this->accessToken}");
        }

        return parent::getUrl($name);
    }

    public function pages(string $userId, int $limit = 100): array
    {
        $result = $this->fetchPages($userId, $limit);
        $pages = $this->filterPages($result['data'] ?? []);
        $originalLimit = $limit;

        while ($originalLimit > count($pages)) {
            // iterate again, with the next page
            $next = $result['paging']['cursors']['after'] ?? null;

            if (!$next) {
                return $pages;
            }

            // Next set
            $limit = $originalLimit - count($pages);

            if ($limit <= 0) {
                return $pages;
            }

            $result = $this->fetchPages($userId, $limit, $next);
            $nextPages = $this->filterPages($result['data'] ?? []);
            $pages = array_merge($pages, $nextPages);
        }

        return array_map(function (array $page) {
            return [
                'id' => $page['id'],
                'name' => $page['name'] ?? $page['id'],
            ];
        }, $pages);
    }

    protected function filterPages(array $pages): array
    {
        return array_values(array_filter($pages, function (array $page) {
            $pageId = $page['id'] ?? null;
            if (!$pageId) {
                return false;
            }

            // You can't manage the page, so no sense displaying it
            $token = $page['access_token'] ?? null;
            if (!$token) {
                return false;
            }

            return true;
        }));
    }

    protected function fetchPages(string $userId, int $limit = 100, ?string $after = null): array
    {
        return $this->get("$userId/accounts", ['limit' => $limit, 'after' => $after]);
    }

    protected function processResponse(Response $response): array
    {
        $result = json_decode($response->getBody(), true);
        $success = $response->getStatusCode() >= 200 && $response->getStatusCode() <= 299;

        if (!$success) {
            $code = $response->getStatusCode() ?? 400;
            $message = $result['error']['message'] ?? ($response->getReasonPhrase() ?? 'Unknown Error');

            throw new \Exception($message, $code);
        }

        return $result;
    }
}
