<?php

declare(strict_types=1);

namespace KupShop\ContentBundle\Util;

use EspressoDev\Instagram\Instagram;
use EspressoDev\Instagram\InstagramException;
use KupShop\KupShopBundle\Context\ContextManager;
use KupShop\KupShopBundle\Util\SettingsUtil;

class InstagramUtil
{
    public const ITEM_TEMPLATE = '{
            "id": null,
              "user": null,
              "images": {
                "thumbnail": {
                  "width": 150,
                  "height": 150,
                  "url": null
                },
                "low_resolution": {
                  "width": 320,
                  "height": 320,
                  "url": null
                },
                "standard_resolution": {
                  "width": 640,
                  "height": 640,
                  "url": null
                }
              },
              "created_time": "1554361307",
              "caption": {
                "id": "17886256120312260",
                "text": null,
                "created_time": "1554361307",
                "from": null
              },
              "user_has_liked": false,
              "likes": {
                "count": null
              },
              "tags": [
              ],
              "filter": "Clarendon",
              "comments": {
                "count": 0
              },
              "type": "image",
              "link": "",
              "location": null,
              "attribution": null,
              "users_in_photo": []
            }';

    public const FEED_TEMPLATE = '{
              "pagination": {
                "next_max_id": "",
                "next_url": ""
              },
              "data": null,
              "meta": {
                "code": 200
              }
            }';

    /** @required */
    public SettingsUtil $settingsUtil;

    /** @required */
    public ContextManager $contextManager;

    public function updateFeed(string $lang, ?string $key = null)
    {
        $languageSettings = \Settings::getFromCache($lang);

        $cfgKey = $this->getSettingsKey('instagram', $key);

        if (!isset($languageSettings->{$cfgKey}['api'])) {
            return [];
        }

        $settings = $languageSettings->{$cfgKey};

        $count = $settings['count'] ?? 10;

        $instagram = new Instagram($settings['api']);

        if (($settings['refresh_time'] ?? time()) <= time()) {
            try {
                $refresh = $instagram->refreshLongLivedToken();
            } catch (InstagramException $e) {
                throw new \InvalidArgumentException('Chyba komunikace. Nepodařilo se obnovit token.');
            }
            if (isset($refresh) && $refresh->access_token) {
                $userProfile = $instagram->getUserProfile();
                if (empty($userProfile->error)) {
                    $settings['api'] = $refresh->access_token;
                    $settings['refresh_time'] = time() + ($refresh->expires_in / 2);
                    $settings['username'] = $userProfile->username;
                    $this->settingsUtil->saveValueInLanguage($lang, $cfgKey, $settings);
                    \Settings::clearCache(true);
                }
            }
        }

        $user = $instagram->getUserProfile();

        if (!$user) {
            throw new \InvalidArgumentException('Chyba komunikace. Instagram nevrátil číslo chyby. Zkuste aktualizovat svůj token na nový.');
        }

        if (isset($user->error)) {
            if (in_array($user->error->code, [10, 100])) {
                throw new \InvalidArgumentException('Chyba komunikace. Aktualizujte svůj token na nový.');
            }

            throw new \InvalidArgumentException($user->error->message);
        }

        $medias = $instagram->getUserMedia('me', $count);

        $item = json_decode(static::ITEM_TEMPLATE, true);

        $result = [];
        foreach (array_slice($medias->data, 0, $count) as $index => $media) {
            $new_item = $item;

            $new_item['id'] = $media->id;
            $new_item['user'] = [
                'pk' => $user->id,
                'username' => $user->username,
            ];
            $thumbnail = $this->getThumbnailFromMedia($media);
            $new_item['images']['thumbnail']['url'] = $thumbnail;
            $new_item['images']['low_resolution']['url'] = $thumbnail;
            $new_item['images']['standard_resolution']['url'] = $thumbnail;
            $new_item['likes']['count'] = null;
            $new_item['caption']['from'] = $media->username;
            $new_item['caption']['text'] = $media->caption ?? '';
            $new_item['link'] = $media->permalink;
            $new_item['created_time'] = \DateTime::createFromFormat(DATE_W3C, $media->timestamp)->getTimestamp();

            $result[] = $new_item;
        }

        $data = json_decode(static::FEED_TEMPLATE, true);
        $data['data'] = $result;

        $this->settingsUtil->saveValueInLanguage($lang, $this->getSettingsKey('instagram_feed', $key), $data, false);

        return $data;
    }

    public function getFeed(string $callback, ?int $count, ?string $key = null)
    {
        $data = $this->getFeedData($count, $key);

        if (!$data) {
            return 'empty';
        }

        $feed = "/**/{$callback}(";

        $feed .= json_encode($data);
        $feed .= ');';

        return $feed;
    }

    public function getFeedData(?int $count, ?string $key = null)
    {
        $data = \Settings::getDefault()->loadValue($this->getSettingsKey('instagram_feed', $key));

        if ($count) {
            $data['data'] = array_slice($data['data'], 0, $count);
        }

        return $data;
    }

    public function getSettingsKey(string $name, ?string $additionalKey = null)
    {
        if ($additionalKey) {
            $name .= '_'.$additionalKey;
        }

        return $name;
    }

    protected function getThumbnailFromMedia(\stdClass $media): string
    {
        switch ($media->media_type) {
            case 'CAROUSEL_ALBUM':
                return $this->getThumbnailFromMedia(reset($media->children->data) ?? new \stdClass());
            case 'VIDEO':
                return $media->thumbnail_url ?? '';
            default:
            case 'IMAGE':
                return $media->media_url ?? '';
        }
    }
}
