<?php
class Instagram
{
    private $load;
    private $registry;

    private $group = 'instagram_access';

    public $userName;
    public $accessToken;
    public $expiresIn;
    public $profileLink;

    public function __construct($registry)
    {
        $this->load = $registry->get('load');
        $this->registry = $registry;
        $this->index();
    }

    public function __get($name)
    {
        return $this->registry->get($name);
    }

    public function index()
    {
        $this->getSetting();

        if ($this->isExpiredToken() && $this->accessToken) {
            $accessToken = $this->refreshAccessToken($this->accessToken);
            if (isset($accessToken['access_token'])) {
                $this->saveToken($accessToken);
                $this->getSetting();
            }
        }
    }

    public function getSetting()
    {
        $this->load->dmodel('setting/setting');
        $setting = $this->dmodel_setting_setting->getSetting($this->group);

        $this->userName = $setting['instagram_access_user_name'] ?? null;
        $this->accessToken = $setting['instagram_access_token_long_duration'] ?? null;
        $this->expiresIn = $setting['instagram_access_expires_in'] ?? null;

        $this->profileLink = 'https://www.instagram.com/' . $this->userName;
    }

    public function isValidToken()
    {
        $media = $this->getMedia($this->accessToken);
        return !isset($media['error']);
    }

    public function isExpiredToken()
    {
        return ((int) $this->expiresIn) < time() + 1;
    }

    public function authorize($instagramUserCode)
    {
        try {
            $token = $this->getToken($instagramUserCode);

            if (!isset($token['access_token'])) {
                throw new Exception('Erro ao buscar o token');
            }

            $accessToken = $token['access_token'];
            $userId = $token['user_id'];

            $tokenLongDuration = $this->getTokenLongDuration($accessToken);

            if (!isset($tokenLongDuration['access_token'])) {
                throw new Exception('Erro ao buscar o token de longa duração');
            }

            $accessTokenLongDuration = $tokenLongDuration['access_token'];

            $instagram_user = $this->getUser($userId, $accessTokenLongDuration);

            if (!isset($instagram_user['username'])) {
                throw new Exception('Erro ao buscar o nome do usuário');
            }

            $tokenLongDuration = $this->refreshAccessToken($accessTokenLongDuration);

            if (!isset($tokenLongDuration['access_token'])) {
                throw new Exception('Erro ao buscar o token de longa duração, somente contas públicas do instagram podem utilizar este módulo');
            }

            $this->load->dmodel('setting/setting');
            $this->dmodel_setting_setting->editSettingForKey($this->group, [
                'instagram_access_user_name' => $instagram_user['username'],
                'instagram_access_token_long_duration' => $tokenLongDuration['access_token'],
                'instagram_access_expires_in' => time() + $tokenLongDuration['expires_in'],
            ]);

            $this->getSetting();

            return ['success' => 1];
        } catch (Exception $e) {
            return ['error' => $e->getMessage()];
        }
    }

    private function fetchAPI($options)
    {
        $ch = curl_init();
        curl_setopt_array($ch, $options);

        $content = curl_exec($ch);

        if (curl_error($ch)) {
            throw new Exception(curl_error($ch));
        }

        curl_close($ch);

        return json_decode($content, true);
    }

    public function getToken($instagramUserCode)
    {
        return $this->fetchAPI([
            CURLOPT_URL => 'https://api.instagram.com/oauth/access_token/',
            CURLOPT_POST => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POSTFIELDS => [
                'client_id' => '421705848720001',
                'client_secret' => '28ddc47ea9f542ef1c4189674eec1347',
                'grant_type' => 'authorization_code',
                'redirect_uri' => 'https://instagramec.futurasistemas.com.br/',
                'code' => $instagramUserCode,
            ],
        ]);
    }

    public function getTokenLongDuration($accessToken)
    {
        return $this->fetchAPI([
            CURLOPT_URL => 'https://graph.instagram.com/access_token?' . http_build_query([
                'grant_type' => 'ig_exchange_token',
                'client_secret' => '28ddc47ea9f542ef1c4189674eec1347',
                'access_token' => $accessToken,
            ]),
            CURLOPT_RETURNTRANSFER => true,
        ]);
    }

    public function getUser($userId, $accessTokenLongDuration)
    {
        return $this->fetchAPI([
            CURLOPT_URL => 'https://graph.instagram.com/' . $userId . '?' . http_build_query([
                'fields' => 'id,username',
                'access_token' => $accessTokenLongDuration,
            ]),
            CURLOPT_RETURNTRANSFER => true,
        ]);
    }

    public function refreshAccessToken($accessTokenLongDuration)
    {
        return $this->fetchAPI([
            CURLOPT_URL => 'https://graph.instagram.com/refresh_access_token?' . http_build_query([
                'grant_type' => 'ig_refresh_token',
                'access_token' => $accessTokenLongDuration,
            ]),
            CURLOPT_RETURNTRANSFER => true,
        ]);
    }

    public function saveToken($tokenLongDuration)
    {
        $this->load->dmodel('setting/setting');
        $this->dmodel_setting_setting->editSettingForKey($this->group, [
            'instagram_access_token_long_duration' => $tokenLongDuration['access_token'],
            'instagram_access_expires_in' => time() + $tokenLongDuration['expires_in']
        ]);
    }

    public function getMedia($instagramAccessTokenLongDuration)
    {
        return $this->fetchAPI([
            CURLOPT_URL => 'https://graph.instagram.com/me/media?' . http_build_query([
                'fields' => 'id,caption,media_type,media_url,permalink,thumbnail_url',
                'access_token' => $instagramAccessTokenLongDuration,
            ]),
            CURLOPT_RETURNTRANSFER => true,
        ]);
    }

    public function getMediaEmbed($instagramAccessTokenLongDuration)
    {
        $mediaInfo = $this->getMedia($instagramAccessTokenLongDuration);
        $media = [];
        if (isset($mediaInfo['data'])) {
            foreach ($mediaInfo['data'] as $info) {
                $media[] = $this->fetchAPI([
                    CURLOPT_URL => "https://graph.facebook.com/v10.0/instagram_oembed?url={$info['permalink']}&access_token=2486820544909228|63c4f00ede6f955aa51ac36cb2175875",
                    CURLOPT_RETURNTRANSFER => true,
                ]);
            }
        }

        return $media;
    }

    public function getAuthorizeUrl($callBackUrl)
    {
        return 'https://www.instagram.com/oauth/authorize?client_id=421705848720001&redirect_uri=https://instagramec.futurasistemas.com.br/&scope=user_profile,user_media&response_type=code&state=' . str_replace(['&', '='], ['|', '~'], $callBackUrl);
    }
}