<?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\ConnectCpCreationClient;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Client\FacebookClient;
use CpCreation\VitiCore\Bridge\Symfony\Bundle\Utils\Mailer;
use CpCreation\VitiCore\SocialNetwork\Model\SocialNetwork;
use CpCreation\VitiCore\SocialNetwork\Repository\SocialNetworkRepository;
use Psr\Cache\CacheItemPoolInterface;

class FacebookInstagramProvider implements SocialNetworkProviderInterface
{
    public const TYPE = 'facebook_instagram';

    private string $accessToken = '';
    private string $instagramId = '';
    private ?SocialNetwork $social = null;

    public function __construct(
        private SocialNetworkRepository $socialNetworkRepository,
        private FacebookClient $client,
        private ConnectCpCreationClient $cpCreationClient,
        private CacheItemPoolInterface $cache,
        private Mailer $mailer,
    ) {
        /** @var SocialNetwork|null $social */
        $social = $this->socialNetworkRepository->findOneBy([
            'network' => self::TYPE,
        ]);

        $this->social = $social;
    }

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

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

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

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

        try {
            $this->loadCredentials();

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

            $response = $this->client->get(
                '/'.$this->instagramId.'/media?fields=media_url,media_type,thumbnail_url,timestamp,caption,ig_id,video_url,permalink&transport=cors&access_token='.$this->accessToken.'&limit='.$count
            );

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

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

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

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

            return $medias;
        } catch (\Throwable $e) {
            $this->mailer->sendErrorInstagram('Facebook Instagram : '.$e->getMessage());

            return [];
        }
    }

    public function getMediasNext(string $token, int $count = 12): array
    {
        try {
            $this->loadCredentials();

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

            $response = $this->client->get(
                '/'.$this->instagramId.'/media?fields=media_url,media_type,thumbnail_url,timestamp,caption,ig_id,video_url,permalink&transport=cors&access_token='.$this->accessToken.'&limit='.$count.'&after='.$token
            );

            /** @var array $payload */
            $payload = json_decode(
                (string) $response->getBody(),
                true,
                512,
                \JSON_THROW_ON_ERROR
            );

            return $payload;
        } catch (\Throwable $e) {
            $this->mailer->sendErrorInstagram('Facebook Instagram next medias : '.$e->getMessage());

            return [];
        }
    }

    public function getMediasBefore(string $token, int $count = 12): array
    {
        try {
            $this->loadCredentials();

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

            $response = $this->client->get(
                '/'.$this->instagramId.'/media?fields=media_url,media_type,thumbnail_url,timestamp,caption,ig_id,video_url,permalink&transport=cors&access_token='.$this->accessToken.'&limit='.$count.'&before='.$token
            );

            /** @var array $payload */
            $payload = json_decode(
                (string) $response->getBody(),
                true,
                512,
                \JSON_THROW_ON_ERROR
            );

            return $payload;
        } catch (\Throwable $e) {
            $this->mailer->sendErrorInstagram('Facebook Instagram previous medias : '.$e->getMessage());

            return [];
        }
    }

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

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

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

        try {
            /** @var array{id?: string, accountInstagram?: string}|mixed $configuration */
            $configuration = $this->social->getConfiguration();

            if (!\is_array($configuration)) {
                return;
            }

            $socialId = $configuration['id'] ?? null;
            $instagramId = $configuration['accountInstagram'] ?? null;

            if (!\is_string($socialId) || '' === $socialId) {
                return;
            }

            if (!\is_string($instagramId) || '' === $instagramId) {
                return;
            }

            $response = $this->cpCreationClient->get('api/client_socials/'.$socialId);

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

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