<?php

/*
 * This file is part of the Fancy Bricks package.
 *
 * (c) Joshua Gugun Siagian <suabahasa@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace Fancy\Animations\Utils;

use _FancyAnimations\FANCY_ANIMATIONS;
use stdClass;
use WP_Upgrader;
/**
 * Lemon Squeezy WordPress Updater.
 *
 * @link https://github.com/Make-Lemonade/lemonsqueezy-wp-updater-example
 *
 * @since 1.0.0
 */
class Updater
{
    /**
     * @var string
     */
    public $plugin_id;
    /**
     * @var string
     */
    public $plugin_slug;
    /**
     * @var string
     */
    public $version;
    /**
     * @var string
     */
    public $api_url;
    /**
     * @var string
     */
    public $cache_key;
    /**
     * @var boolean
     */
    public $cache_allowed = \true;
    /**
     * @param string $plugin_id   The ID of the plugin.
     * @param string $plugin_slug The slug of the plugin.
     * @param string $version     The current version of the plugin.
     * @param string $api_url     The API URL to the update server.
     */
    public function __construct($plugin_id, $plugin_slug, $version, $api_url)
    {
        $this->plugin_id = $plugin_id;
        $this->plugin_slug = $plugin_slug;
        $this->version = $version;
        $this->api_url = $api_url;
        $this->cache_key = \str_replace('-', '_', $this->plugin_slug) . '_updater';
        // Only disable this for debugging
        \add_filter('plugins_api', fn($result, $action, $args) => $this->info($result, $action, $args), 20, 3);
        \add_filter('site_transient_update_plugins', fn($transient) => $this->update($transient));
        \add_action('upgrader_process_complete', function ($wpUpgrader, $options) : void {
            $this->purge($wpUpgrader, $options);
        }, 10, 2);
    }
    /**
     * Fetch the update info from the remote server running the Lemon Squeezy plugin.
     *
     * @return object|bool
     */
    public function request()
    {
        $lsq_license_key = $this->get_license_key();
        if ($lsq_license_key === '' || $lsq_license_key === '0') {
            return \false;
        }
        $remote = \get_transient($this->cache_key);
        if ($remote !== \false && $this->cache_allowed) {
            if ($remote === 'error') {
                return \false;
            }
            try {
                return \json_decode($remote, null, 512, \JSON_THROW_ON_ERROR);
            } catch (\JsonException $e) {
                return \false;
            }
        }
        $remote = \wp_remote_get($this->api_url . \sprintf('/update?license_key=%s', $lsq_license_key), ['timeout' => 10]);
        if (\is_wp_error($remote) || \wp_remote_retrieve_response_code($remote) !== 200 || empty(\wp_remote_retrieve_body($remote))) {
            \set_transient($this->cache_key, 'error', \MINUTE_IN_SECONDS * 10);
            return \false;
        }
        $payload = \wp_remote_retrieve_body($remote);
        \set_transient($this->cache_key, $payload, \DAY_IN_SECONDS);
        try {
            return \json_decode($payload, null, 512, \JSON_THROW_ON_ERROR);
        } catch (\JsonException $e) {
            return \false;
        }
    }
    /**
     * Override the WordPress request to return the correct plugin info.
     *
     * @see https://developer.wordpress.org/reference/hooks/plugins_api/
     *
     * @param false|object|array $result
     * @param string $action
     * @param object $args
     * @return object|bool
     */
    public function info($result, $action, $args)
    {
        if ($action !== 'plugin_information') {
            return \false;
        }
        if ($this->plugin_slug !== $args->slug) {
            return \false;
        }
        $remote = $this->request();
        if (!$remote || !$remote->success || empty($remote->update)) {
            return \false;
        }
        $plugin_data = \get_plugin_data(__FILE__);
        $result = $remote->update;
        $result->name = $plugin_data['Name'];
        $result->slug = $this->plugin_slug;
        $result->sections = (array) $result->sections;
        return $result;
    }
    /**
     * Override the WordPress request to check if an update is available.
     *
     * @see https://make.wordpress.org/core/2020/07/30/recommended-usage-of-the-updates-api-to-support-the-auto-updates-ui-for-plugins-and-themes-in-wordpress-5-5/
     *
     * @param object $transient
     * @return object
     */
    public function update($transient)
    {
        if (empty($transient->checked)) {
            return $transient;
        }
        $res = (object) ['id' => $this->plugin_id, 'slug' => $this->plugin_slug, 'plugin' => $this->plugin_id, 'new_version' => $this->version, 'url' => '', 'package' => '', 'icons' => [], 'banners' => [], 'banners_rtl' => [], 'tested' => '', 'requires_php' => '', 'compatibility' => new stdClass()];
        $remote = $this->request();
        if ($remote && $remote->success && !empty($remote->update) && \version_compare($this->version, $remote->update->version, '<')) {
            $res->new_version = $remote->update->version;
            $res->package = $remote->update->download_link;
            $transient->response[$res->plugin] = $res;
        } else {
            $transient->no_update[$res->plugin] = $res;
        }
        return $transient;
    }
    /**
     * When the update is complete, purge the cache.
     *
     * @see https://developer.wordpress.org/reference/hooks/upgrader_process_complete/
     *
     * @param WP_Upgrader $upgrader
     * @param array $options
     */
    public function purge($upgrader, $options)
    {
        if ($this->cache_allowed && $options['action'] === 'update' && $options['type'] === 'plugin' && !empty($options['plugins'])) {
            foreach ($options['plugins'] as $plugin) {
                if ($plugin === $this->plugin_id) {
                    \delete_transient($this->cache_key);
                }
            }
        }
    }
    public function deactivate_license($license_key, $instance_id)
    {
        $activation_url = \add_query_arg(['license_key' => $license_key, 'instance_id' => $instance_id], $this->api_url . '/deactivate');
        $response = \wp_remote_get($activation_url, ['sslverify' => \false, 'timeout' => 10]);
        if (\wp_remote_retrieve_response_code($response) === 200) {
            \delete_option(FANCY_ANIMATIONS::WP_OPTION . '_license_message');
        }
    }
    public function activate_license($license_key)
    {
        $activation_url = \add_query_arg(['license_key' => $license_key, 'instance_name' => \home_url()], $this->api_url . '/activate');
        $response = \wp_remote_get($activation_url, ['sslverify' => \false, 'timeout' => 10]);
        if (\is_wp_error($response) || \wp_remote_retrieve_response_code($response) !== 200 && \wp_remote_retrieve_response_code($response) !== 400 || empty(\wp_remote_retrieve_body($response))) {
            return;
        }
        \update_option(FANCY_ANIMATIONS::WP_OPTION . '_license_message', \wp_remote_retrieve_body($response));
    }
    public function is_activated() : bool
    {
        $license_message = new \stdClass();
        try {
            $license_message = \json_decode(\get_option(FANCY_ANIMATIONS::WP_OPTION . '_license_message', '{}'), null, 512, \JSON_THROW_ON_ERROR);
        } catch (\JsonException $e) {
        }
        return isset($license_message->data->activated) && $license_message->data->activated;
    }
    /**
     * Get the license key. Normally, your plugin would have a settings page where
     * you ask for and store a license key. Fetch it here.
     *
     * @return string
     */
    protected function get_license_key()
    {
        // See class-settings-page.php
        $license = \get_option(FANCY_ANIMATIONS::WP_OPTION . '_license', ['key' => '']);
        return $license['key'] ?? null;
    }
}
