<?php

declare(strict_types=1);

/*
 * This file is part of the VitiCore 2.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CpCreation\VitiCore\Bridge\Symfony\Bundle\Provider\SocialNetwork;

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Client\BasicInstagramClient;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Client\ConnectCpCreationClient;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Client\InstagramClient;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Service\EncryptOpenSSl;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Utils\Mailer;
use CpCreation\VitiCore\SocialNetwork\Model\SocialNetworkNew;
use CpCreation\VitiCore\SocialNetwork\Repository\SocialNetworkNewRepository;
use GuzzleHttp\Psr7\Uri;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RouterInterface;

class BasicInstagramProvider implements SocialNetworkProviderInterface
{
    public const TYPE = 'basic_instagram';

    private string $accessToken = '';
    private string $userId = '';
    private ?SocialNetworkNew $social = null;

    public function __construct(
        private SocialNetworkNewRepository $socialNetworkNewRepository,
        private BasicInstagramClient $client,
        private ConnectCpCreationClient $cpCreationClient,
        private InstagramClient $apiInstagramClient,
        private CacheItemPoolInterface $cache,
        private EncryptOpenSSl $encrypt,
        private RouterInterface $router,
        private Mailer $mailer,
        private string $clientIdAppInstagram,
    ) {
        /** @var SocialNetworkNew|null $social */
        $social = $this->socialNetworkNewRepository->findOneBy([
            'network' => self::TYPE,
        ]);

        $this->social = $social;
    }

    public function getMedias(int $count): array
    {
        if (null === $this->social) {
            return [];
        }

        $cacheItem = $this->cache->getItem('news.instagram');

        if ($cacheItem->isHit()) {
            $cached = $cacheItem->get();

            return \is_array($cached) ? $cached : [];
        }

        try {
            $this->loadCredentials();

            if ('' === $this->accessToken) {
                return [];
            }

            $result = $this->client->get(
                'me/media',
                [
                    'query' => [
                        'access_token' => $this->accessToken,
                        'fields' => 'id,caption,media_type,media_url,permalink,timestamp,thumbnail_url,username',
                        'limit' => $count,
                    ],
                ]
            );

            /** @var array{data?: array} $response */
            $response = json_decode(
                $result->getBody()->getContents(),
                true,
                512,
                \JSON_THROW_ON_ERROR
            );

            $medias = isset($response['data']) && \is_array($response['data'])
                ? $response['data']
                : [];

            $cacheItem->expiresAfter(180);
            $cacheItem->set($medias);
            $this->cache->save($cacheItem);

            $this->social->setData($medias);
            $this->socialNetworkNewRepository->save($this->social);

            return $medias;
        } catch (\Throwable $e) {
            $this->mailer->sendErrorInstagram($e->getMessage());

            return [];
        }
    }

    public function loginUrl(Request $request): string
    {
        /** @var Uri $uri */
        $uri = $this->cpCreationClient->getConfig()['base_uri'];

        $redirectUri = $uri->getScheme().'://'.$uri->getHost().$uri->getPath().'request/instagram/callback';

        $encryptedUri = $this->encrypt->encrypt(
            $request->getScheme().'://'.$request->getHost().$this->router->generate('admin_socialNew')
        );

        $params = [
            'client_id' => $this->clientIdAppInstagram,
            'redirect_uri' => $redirectUri,
            'scope' => 'instagram_business_basic,instagram_business_content_publish',
            'response_type' => 'code',
            'state' => $encryptedUri,
        ];

        /** @var Uri $uriApiInstagram */
        $uriApiInstagram = $this->apiInstagramClient->getConfig()['base_uri'];

        return $uriApiInstagram->getScheme()
            .'://'
            .$uriApiInstagram->getHost()
            .$uriApiInstagram->getPath()
            .'oauth/authorize?'
            .http_build_query($params);
    }

    public function getNetwork(): string
    {
        return self::TYPE;
    }

    private function loadCredentials(): void
    {
        if ('' !== $this->accessToken && '' !== $this->userId) {
            return;
        }

        if (null === $this->social) {
            return;
        }

        try {
            $response = $this->cpCreationClient->get(
                'api/client_socials/'.$this->social->getConnectId()
            );

            /** @var array{token?: scalar|null, userId?: scalar|null} $result */
            $result = json_decode(
                $response->getBody()->getContents(),
                true,
                512,
                \JSON_THROW_ON_ERROR
            );

            $this->accessToken = isset($result['token']) ? (string) $result['token'] : '';
            $this->userId = isset($result['userId']) ? (string) $result['userId'] : '';
        } catch (\Throwable $e) {
            $this->mailer->sendErrorConnexionApiConnectSocialInstagram($e->getMessage());
        }
    }
}
