<?php
namespace KaliForms\Inc\Utils;

if (!defined('ABSPATH')) {
    exit;
}
use KaliForms\Inc\Backend\Notifications\Notification;

class KaliForms_Store
{
    /**
     * Currend endpoint
     *
     * @var string
     */
    public $api_url = 'https://www.kaliforms.com/';
    /**
     * Plugin slug
     *
     * @var string
     */
    public $slug = 'kaliforms-pro';
    /**
     * Parent plugin slug
     *
     * @var string
     */
    public $parent_slug = 'kaliforms';
    /**
     * Known extensions
     *
     * @var array
     */
    public $known_extensions = [];
    /**
     * Extensions
     *
     * @var array
     */
    public $extensions = [];
    /**
     * Class constructor
     */
    public function __construct()
    {
        add_action('admin_init', [$this, 'check_license']);
        add_action('admin_init', [$this, 'updater'], 0);

        $actions = $this->allowed_actions();
        $this->_register_allowed_actions($actions);

        add_filter($this->parent_slug . '_hook_external_notifications', [$this, '_register_global_notifications']);
    }
    /**
     * Returns an instance of the plugin
     *
     * @return KaliForms_Store
     */
    public static function get_instance()
    {
        static $inst;
        if (!$inst) {
            $inst = new KaliForms_Store();
        }

        return $inst;
    }
    /**
     * Register allowed actions
     *
     * @param [type] $actions
     * @return void
     */
    protected function _register_allowed_actions($actions)
    {
        foreach ($actions['strict'] as $action) {
            if (!method_exists($this, $action)) {
                continue;
            }

            add_action('wp_ajax_' . $this->parent_slug . '_' . $action,
                [$this, $action]
            );

            add_action('wp_ajax_nopriv_' . $this->parent_slug . '_' . $action,
                [$this, 'denied']
            );
        }

        foreach ($actions['public'] as $action) {
            if (!method_exists($this, $action)) {
                continue;
            }

            add_action('wp_ajax_' . $this->parent_slug . '_' . $action,
                [$this, $action]
            );

            add_action('wp_ajax_nopriv_' . $this->parent_slug . '_' . $action,
                [$this, $action]
            );
        }
    }
    /**
     * Returns a list of allowed actions
     *
     * @return array
	 */
    public function allowed_actions()
    {
        return [
            'strict' => [
                'install_plugin_from_store',
                'activate_plugin_from_store',
                'reload_extensions',
                'install_plugin',
                'activate_license_from_store',
                'deactivate_license_from_store',
                'add_master_key',
                'remove_master_key',
                'get_kf_auth',
                'delete_kf_auth',
                'set_old_licensing',
                'update_license_key_manually',
                'check_license_key_manually',
                'get_license_key',
                'activate_license_manually',
				'deactivate_license_manually'
            ],
            'public' => [],
        ];
    }
    /**
     *  Deny access
     */
    public function denied()
    {
        wp_die(esc_html__('Denied', 'kaliforms'));
    }
    /**
     * Retrieves a list of plugins available for download/install from kali forms
     *
     * @return array
	 */
    public function get_needed_plugin_data()
    {
        $this->get_extensions();
        $this->get_installed_plugins();

        return $this->known_extensions;
    }
    /**
     * Create an array of plugins
     *
     * @return void
     */
    public function get_installed_plugins()
    {
        $this->known_extensions = [
            'kali-forms-pro' => '',
        ];

        foreach ($this->extensions as $k => $v) {
            $this->known_extensions[$v['slug']] = '';
        }

        $plugins = get_plugins();
        foreach ($this->known_extensions as $k => $v) {
            $this->known_extensions[$k] = array_key_exists($k . '/' . $k . '.php', $plugins) ? 'installed' : 'not-installed';
            if ($this->known_extensions[$k] === 'installed') {
                $this->known_extensions[$k] = is_plugin_active($k . '/' . $k . '.php') ? 'active' : 'installed';
            }
        }
    }
    /**
     * Gets extensions from the rest API
     *
     * @return void
     */
    public function get_extensions()
    {
        $this->extensions = get_transient($this->slug . '_extensions');
        if (false === $this->extensions) {
            $this->extensions = [];
            $this->get_extensions_request();
        }
    }
    /**
     * Make the request to our API
     *
     * @return void
     */
    public function get_extensions_request()
    {
        $url      = KALIFORMS_EXTENSIONS_API;
        $response = wp_remote_get($url);

        if (!is_wp_error($response)) {
            $data = json_decode(wp_remote_retrieve_body($response), true);
            if (!empty($data) && is_array($data)) {
                set_transient($this->slug . '_extensions', $data, 2 * DAY_IN_SECONDS);

                $this->extensions = $data;
            }
        }
    }
    /**
     * Reloads extensions
     *
     * @return void
     */
    public function reload_extensions()
    {
        check_admin_referer('kaliforms_extensions_nonce', 'nonce');
        delete_transient('kaliforms_extensions');
        wp_die(json_encode(['status' => 'ok']));
    }
    /**
     * Get KF Auth
     *
     * @return void
     */
    public function get_kf_auth()
    {
        check_admin_referer('kaliforms_store_nonce', 'nonce');
        $store = KaliForms_Store::get_instance();
        $auth  = $store->get_stored_auth();
        wp_die(json_encode([
            'status'      => 'ok',
            'accessToken' => !empty($auth['access_token']) ? $auth['access_token'] : null,
        ]));
    }

    public function delete_kf_auth()
    {
        check_admin_referer('kaliforms_store_nonce', 'nonce');
        $store = KaliForms_Store::get_instance();
        $store->deauthenticate();
        wp_die(json_encode([
            'status'      => 'ok',
            'accessToken' => null,
        ]));

    }
    public function set_old_licensing()
    {
        check_admin_referer('kaliforms_store_nonce', 'nonce');
        update_option('kaliforms_pro_old_licensing', $_POST['old_licensing']);
        wp_die(json_encode(['status' => 'ok']));
    }
    /**
     * Add master key ( FOR LEGACY PURPOSES )
     *
     * @return void
     */
    public function add_master_key()
    {
        check_admin_referer('kaliforms_store_nonce', 'nonce');
        update_option('kaliforms_pro_license_key', wp_unslash($_POST['master_key']));
        update_option('kaliforms_pro_license_status', 'valid');
        wp_die(json_encode(['status' => 'ok']));
    }
    /**
     * Remove master key
     *
     * @return void
     */
    public function remove_master_key()
    {
        check_admin_referer('kaliforms_store_nonce', 'nonce');
        delete_option('kaliforms_pro_license_key');
        delete_option('kaliforms_pro_license_status');
        wp_die(json_encode(['status' => 'ok']));
    }
    /**
     * Update master key manually
     *
     * @return void
     */
    public function update_license_key_manually()
    {
        check_admin_referer('kaliforms_store_nonce', 'nonce');
        update_option('kaliforms_pro_license_key', wp_unslash($_POST['license_key']));
        update_option('kaliforms_pro_license_status', 'waiting');
        wp_die(json_encode(['status' => 'ok']));
    }
    /**
     * Check license key manually
     *
     * @return void
     */
    public function check_license_key_manually()
    {
        check_admin_referer('kaliforms_store_nonce', 'nonce');
        $license_data = $this->check_license_legacy();
        wp_die(json_encode(['data' => $license_data]));
    }
    /**
     * Activates a license manually
     *
     * @return void
     */
    public function activate_license_manually()
    {
        check_admin_referer('kaliforms_store_nonce', 'nonce');
        $license = trim(get_option('kaliforms_pro_license_key'));
        // data to send in our API request
        $api_params = [
            'edd_action' => 'activate_license',
            'license'    => $license,
            'item_id'    => 218, // the name of our product in EDD
            'url'        => home_url(),
        ];
        // Call the custom API.
        $response = wp_remote_post($this->api_url, ['timeout' => 15, 'sslverify' => false, 'body' => $api_params]);

        // make sure the response came back okay
        if (is_wp_error($response)) {
            wp_die('error');
        }

        $license_data = json_decode(wp_remote_retrieve_body($response));
        // $license_data->license will be either "valid" or "invalid"
        update_option('kaliforms_pro_license_status', $license_data->license);
        if ('valid' != $license_data->license) {
            wp_die('error');
        }
        wp_die('success');
    }
    /**
     * Activates a license manually
     *
     * @return void
     */
    public function deactivate_license_manually()
    {
        check_admin_referer('kaliforms_store_nonce', 'nonce');
        $license = trim(get_option('kaliforms_pro_license_key'));
        // data to send in our API request
        $api_params = [
            'edd_action' => 'deactivate_license',
            'license'    => $license,
            'item_id'    => 218, // the name of our product in EDD
            'url'        => home_url(),
        ];
        // Call the custom API.
        $response = wp_remote_post($this->api_url, ['timeout' => 15, 'sslverify' => false, 'body' => $api_params]);

        // make sure the response came back okay
        if (is_wp_error($response)) {
            wp_die('error');
        }

        $license_data = json_decode(wp_remote_retrieve_body($response));
        // $license_data->license will be either "valid" or "invalid"
        if ('deactivated' != $license_data->license) {
            wp_die('error');
        }
        update_option('kaliforms_pro_license_status', 'waiting');
        wp_die('success');
    }
    /**
     * Get license key
     *
     * @return void
     */
    public function get_license_key()
    {
        check_admin_referer('kaliforms_store_nonce', 'nonce');
        wp_die(json_encode([
            'license_key'    => get_option('kaliforms_pro_license_key', ''),
            'license_status' => get_option('kaliforms_pro_license_status', ''),
        ]));
    }
    /**
     * Returns an activation url that will be used in javascript to activate
     *
     * @return void
     */
    public function activate_plugin_from_store()
    {
        check_admin_referer('kaliforms_store_nonce', 'nonce');
        if (!isset($_POST['download'])) {
            wp_die(json_encode(false));
        }
        $_POST['download'] = wp_unslash($_POST['download']);

        $activate_url = $this->_create_plugin_activation_url($_POST['download']);

        wp_die(json_encode(['url' => $activate_url]));
    }
    /**
     * Creates a plugin activation URL
     *
     * @param [type] $name
     * @return void
     */
    protected function _create_plugin_activation_url($name)
    {
        $name            = strtolower(str_replace(' ', '-', $name));
        $plugin_basename = $name . '/' . $name . '.php';

        $activate_url = add_query_arg(
            [
                'action'        => 'activate',
                'plugin'        => rawurlencode($plugin_basename),
                'plugin_status' => 'all',
                'paged'         => '1',
                '_wpnonce'      => wp_create_nonce('activate-plugin_' . $plugin_basename),
            ],
            admin_url('plugins.php')
        );

        return $activate_url;
    }
    /**
     * Activates a license from store
     *
     * @return void
     */
    public function activate_license_from_store()
    {
        check_admin_referer('kaliforms_store_nonce', 'nonce');
        if (!isset($_POST['subscription'])) {
            wp_die(json_encode(false));
        }
    }
    /**
     * Deactivates license from store
     *
     * @return void
     */
    public function deactivate_license_from_store()
    {
        check_admin_referer('kaliforms_store_nonce', 'nonce');
        if (!isset($_POST['subscription'])) {
            wp_die(json_encode(false));
        }
    }

    /**
     * Install plugin from store
     *
     * @return void
     */
    public function install_plugin_from_store()
    {
        check_admin_referer('kaliforms_store_nonce', 'nonce');
        $_POST['download_url'] = wp_unslash($_POST['download_url']);

        // Install the addon.
        if (isset($_POST['download_url'])) {
            $download_url = esc_url($_POST['download_url']);
            global $hook_suffix;
            // Let only plugins from our site.
            if (0 !== strpos($download_url, 'https://kaliforms.com')) {
                // Send back a response.
                wp_die(json_encode(false));
            }

            // Set the current screen to avoid undefined notices.
            set_current_screen();

            // We do not need any extra credentials if we have gotten this far, so let's install the plugin.
            require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';

            // Create the plugin upgrader with our custom skin.
            $installer = new \Plugin_Upgrader();
            $installer->install($download_url);

            // Flush the cache and return the newly installed plugin basename.
            wp_cache_flush();
            if ($installer->plugin_info()) {
                $plugin_basename = $installer->plugin_info();
                $activate_url    = add_query_arg(
                    [
                        'action'        => 'activate',
                        'plugin'        => rawurlencode($plugin_basename),
                        'plugin_status' => 'all',
                        'paged'         => '1',
                        '_wpnonce'      => wp_create_nonce('activate-plugin_' . $plugin_basename),
                    ],
                    admin_url('plugins.php')
                );

                wp_die(json_encode([
                    'plugin'       => $plugin_basename,
                    'activate_url' => $activate_url,
                ]));
            }
        }

        wp_die(json_encode(false));
    }

    /**
     * Installs plugin
     * @deprecated - everything will be moved to install_plugin_from_store
     * @return void
     */
    public function install_plugin()
    {
        check_admin_referer('kaliforms_extensions_nonce', 'nonce');

        // Install the addon.
        if (isset($_POST['download_url'])) {
            $download_url = esc_url($_POST['download_url']);
            global $hook_suffix;
            // Let only plugins from our site.
            if (0 !== strpos($download_url, 'https://kaliforms.com')) {
                // Send back a response.
                wp_die(json_encode(false));
            }

            // Set the current screen to avoid undefined notices.
            set_current_screen();

            // We do not need any extra credentials if we have gotten this far, so let's install the plugin.
            require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';

            // Create the plugin upgrader with our custom skin.
            $installer = new \Plugin_Upgrader();
            $installer->install($download_url);

            // Flush the cache and return the newly installed plugin basename.
            wp_cache_flush();
            if ($installer->plugin_info()) {
                $plugin_basename = $installer->plugin_info();
                $activate_url    = add_query_arg(
                    array(
                        'action'        => 'activate',
                        'plugin'        => rawurlencode($plugin_basename),
                        'plugin_status' => 'all',
                        'paged'         => '1',
                        '_wpnonce'      => wp_create_nonce('activate-plugin_' . $plugin_basename),
                    ),
                    admin_url('plugins.php')
                );

                wp_die(json_encode([
                    'plugin'       => $plugin_basename,
                    'activate_url' => $activate_url,
                ]));
            }
        }

        wp_die(json_encode(false));
    }

    /**
     * Updater function
     *
     * @return void
     */
    public function updater()
    {
        // retrieve our license key from the DB
        $license = get_option('kaliforms_pro_license_key');
        $status  = get_option('kaliforms_pro_license_status');

        // setup the updater
        new Plugin_Updater($this->api_url, KALIFORMS_PRO_PLUGIN_FILE,
            [
                'version' => KALIFORMS_PRO_VERSION,
                'license' => $license,
                'item_id' => 218,
                'author'  => 'Kali Forms',
            ],
            [
                'license_status' => $status,
                'admin_page_url' => admin_url('edit.php?post_type=kaliforms_forms&page=kaliforms-license'),
                'purchase_url'   => 'https://www.kaliforms.com/pricing',
                'plugin_title'   => 'Kali Forms Pro',
            ]
        );
    }

    /**
     * Check license action
     *
     * @return void
     */
    public function check_license()
    {
        if (get_transient('kaliforms_pro_license_status_checking')) {
            return;
        }

        $license    = trim(get_option('kaliforms_pro_license_key'));
        $api_params = [
            'edd_action' => 'check_license',
            'license'    => $license,
            'item_id'    => 218,
            'url'        => home_url(),
        ];
        // Call the custom API.
        $response = wp_remote_post(
            $this->api_url,
            [
                'timeout'   => 15,
                'sslverify' => false,
                'body'      => $api_params,
            ]
        );
        if (is_wp_error($response)) {
            return false;
        }

        $license_data = json_decode(
            wp_remote_retrieve_body($response)
        );

        if ($license_data->license != 'valid') {
            delete_option('kaliforms_pro_license_status');
        }
        // Set to check again in 12 hours
        set_transient(
            'kaliforms_pro_license_status_checking',
            $license_data,
            (60 * 60 * 12)
        );
    }
    public function check_license_legacy()
    {
        if (get_transient('kaliforms_pro_license_status_checking')) {
            return get_transient('kaliforms_pro_license_status_checking');
        }

        $license = trim(get_option('kaliforms_pro_license_key'));

        $api_params = [
            'edd_action' => 'check_license',
            'license'    => $license,
            'item_id'    => 218,
            'url'        => home_url(),
        ];

        // Call the custom API.
        $response = wp_remote_post(
            $this->api_url,
            [
                'timeout'   => 15,
                'sslverify' => false,
                'body'      => $api_params,
            ]
        );
        if (is_wp_error($response)) {
            return false;
        }

        $license_data = json_decode(
            wp_remote_retrieve_body($response)
        );

        if ($license_data->license != 'valid') {
            update_option('kaliforms_pro_license_status', 'waiting');
        }

        // Set to check again in 12 hours
        set_transient(
            'kaliforms_pro_license_status_checking',
            $license_data,
            (60 * 60 * 12)
        );

        return $license_data;
    }
    /**
     * Make the actual request
     *
     * @param [type] $api_params
     * @return void
     */
    public function make_request($api_params)
    {
        $response = wp_remote_post($this->api_url, ['body' => $api_params, 'timeout' => 15, 'sslverify' => false]);
        if (is_wp_error($response)) {
            return false;
        }
        $license_data = json_decode(wp_remote_retrieve_body($response));
        return $license_data;
    }

    /**
     * When we redirect back to wp backend, it means that we are authenticated.
     */
    public function authenticate($data)
    {
        update_option($this->parent_slug . '_kf_auth', [
            'access_token'  => $data['access_token'],
            'refresh_token' => $data['refresh_token'],
            'timestamp'     => time(),
        ]);
    }
    /**
     * Removes option from database
     *
     * @return void
     */
    public function deauthenticate()
    {
        delete_option($this->parent_slug . '_kf_auth');
        delete_option($this->parent_slug . '_pro_license_key');
        delete_option($this->parent_slug . '_pro_license_status');
    }
    /**
     * Refreshes the token
     *
     * @param [type] $refresh_token
     * @return void
     */
    public function refresh_token($refresh_token, $repeat = true)
    {
        $request = wp_remote_get(
            KALIFORMS_API . 'store/refresh?refresh_token=' . $refresh_token,
            [
                'headers' => [
                    'Cache-Control' => 'no-cache',
                ],
            ]
        );
        $response  = wp_remote_retrieve_body($request);
        $auth_data = json_decode($response, true);

        if ($auth_data === null && $repeat) {
            return $this->refresh_token($refresh_token, false);
        }

        $this->store_auth($auth_data);
        return $auth_data;
    }
    /**
     * Gets the stored auth array
     *
     * @return void
     */
    public function get_stored_auth()
    {
        $auth = get_option($this->parent_slug . '_kf_auth', false);
        if (!$auth) {
            return [];
        }

        if (time() > $auth['timestamp'] + 3600) {
            if (empty($auth['refresh_token'])) {
                return new \WP_Error('kf_no_refresh_token', esc_html__('Provide a refresh token.', 'kaliforms'));
            }

            $auth = $this->refresh_token($auth['refresh_token']);
        }

        return $auth;
    }
    /**
     * Stores authentification data
     *
     * @param [type] $data
     * @return void
     */
    public function store_auth($data)
    {
        if (!isset($data['access_token']) && !isset($data['refresh_token'])) {
            return;
        }
        update_option($this->parent_slug . '_kf_auth', [
            'access_token'  => $data['access_token'],
            'refresh_token' => $data['refresh_token'],
            'timestamp'     => time(),
        ]);
    }

    /**
     * Register global notifications
     *
     * @param [type] $notifications
     * @return void
     */
    public function _register_global_notifications($notifications)
    {
        $whitelist = [
            '127.0.0.1',
            '::1',
        ];
        if (!in_array($_SERVER['REMOTE_ADDR'], $whitelist)) {
            return $notifications;
        }

        $option = get_option('kaliforms_pro_license_status', false);
        if ($option === 'valid') {
            return $notifications;
        }

        $auth = $this->get_stored_auth();
        if (is_wp_error($auth) || empty($auth['access_token'])) {
            $notifications[] = new Notification(
                'plugin_login_needed',
                'info',
                esc_html__('Please authenticate and activate your license of Kali Forms Pro for this website.', 'kaliforms'),
                'redirect',
                admin_url('edit.php?post_type=kaliforms_forms&page=kaliforms-store-auth'),
                false
            );

            return $notifications;
        }

        $notifications[] = new Notification(
            'plugin_license_activation_needed',
            'info',
            esc_html__('Please activate your license of Kali Forms Pro for this website.', 'kaliforms'),
            'redirect',
            admin_url('edit.php?post_type=kaliforms_forms&page=kaliforms-store-auth'),
            false
        );

        return $notifications;
    }
}
