<?php
/**
 * Readabler
 * Web accessibility for Your WordPress site.
 * Exclusively on https://1.envato.market/readabler
 *
 * @encoding        UTF-8
 * @version         2.0.5
 * @copyright       (C) 2018-2025 Merkulove ( https://merkulov.design/ ). All rights reserved.
 * @license         Envato License https://1.envato.market/KYbje
 * @contributors    Dmytro Merkulov (dmitry@merkulov.design)
 * @support         help@merkulov.design
 **/

namespace Merkulove\Readabler\Unity;

use WP_Error;

final class Activator
{
    /**
     * Return Activation Status.
     * @return boolean True if activated.
     */
    public static function status(): bool
    {
        // Not activated if plugin doesn't have Envato ID
        if (!defined('READABLER') || !isset(READABLER['envato_id'])) {
            return false;
        }

        // Get actual purchase code
        $purchase_code = Plugin::get_purchase_code();
        if (empty($purchase_code)) {
            return false;
        }

        // Get activation status from transient
	    $transient_key = 'mdp_' . Plugin::get_slug() . '_pid_' . $purchase_code;
        $transient_activation = get_transient($transient_key);
        if (!$transient_activation) {

            // Migration
            $migrated_status = self::migrate_status($purchase_code);
            if ($migrated_status) {
                set_transient($transient_key, true, WEEK_IN_SECONDS);
                return true;
            }

            // Remote check
            $remote_status = self::remote_validation($purchase_code);
            set_transient($transient_key, (bool)$remote_status, WEEK_IN_SECONDS);
            delete_transient( 'mdp_' . Plugin::get_slug() . '_plugin_info' );
            return (bool)$remote_status;

        } else {

            return (bool)$transient_activation;

        }

    }

    /**
     * Remote validation.
     * @param $purchase_code
     * @return bool|mixed|null
     */
    private static function remote_validation($purchase_code)
    {
        // Check a flag to prevent multiple requests
        $flag_key = 'mdp_' . Plugin::get_slug() . '_remote_validation_flag';
        $flag = get_transient($flag_key);
        if (!$flag) {
            set_transient($flag_key, true, 60);
        } else {
            return false;
        }

        switch (2) {
            case 2:
                $remote_status = self::remote_validation_v2($purchase_code);
                break;

            case 1:
            default:
                $remote_status = self::remote_validation_v1($purchase_code);
                break;
        }

        delete_transient($flag_key); // Remove flag

        return $remote_status;
    }

    /**
     * Handles the migration of the activation status.
     *
     * @access private
     * @param string $purchase_code The purchase code used for validation and retrieving activation status.
     * @return bool True if successfully migrated activation status, false otherwise.
     */
    private static function migrate_status(string $purchase_code): bool
    {
        // Migration code
        $cache = new Cache();
        $key = 'activation_' . $purchase_code;
        $cached_activation = $cache->get($key, false);

        // Use activation from cache
        if (!empty($cached_activation)) {
            $cached_activation = json_decode($cached_activation, true);
            // TODO: Remove old cache
            return (bool)$cached_activation[$key];
        } else {
            return false;
        }
    }

    /**
     * Remote validation for version 2.
     *
     * @param string $purchase_code
     * @return bool
     */
    private static function remote_validation_v2(string $purchase_code): bool
    {
        // Get remote validation response
        $response = self::remote_request_v2($purchase_code);

        // Check if the response is valid
        if (is_wp_error($response)) {
            return false;
        }

        // Check if the response is valid
        if (wp_remote_retrieve_response_code($response) !== 200) {
            return false;
        }

        // Decode the response
        $body = wp_remote_retrieve_body($response);
        $response_body = json_decode($body, true);
        if (!$response_body) {
            return false;
        }

        // Check if the response is successful
        if (!$response_body['success']) {
            return false;
        }

        // Check if the response is valid
        $valid = $response_body['data']['valid'] ?? false;

        return (bool)$valid;
    }

    /**
     * Remote validation for version 1.
     * @param string $purchase_code
     * @return bool|mixed
     */
    private static function remote_validation_v1(string $purchase_code)
    {

        /** Get options and define server form plugin setting */
        $options = Settings::get_instance()->options;
        $server = $options['update_server'] ?? 'main';

        /** Remote request to validate purchase code */
        if ($server === 'main') {
            $request = self::remote_request_merkulove_host($purchase_code);
        } else {
            $request = self::remote_request_s1_v1($purchase_code);
        }

        /** We’ll check whether the answer is correct. */
        if (is_wp_error($request)) {
			$transient_key = 'mdp_' . Plugin::get_slug() . '_activation_error';
            delete_transient($transient_key);
            set_transient(
	            $transient_key,
                $request->errors ?? array(),
                60
            );

            return false;

        }

        /** Have answer with wrong code. */
        if (wp_remote_retrieve_response_code($request) !== 200) {
            return false;
        }

        /** Check if we have a valid JSON. */
        $json = json_decode($request['body'], true);

        if ($server === 'main') {

            return true === $json;

        } else {

            // Save remote validation errors to transient
            if (!$json['valid'] ?? false) {
				$transient_key = 'mdp_' . Plugin::get_slug() .  '_remote_validation_errors';
                delete_transient($transient_key);
                set_transient(
	                $transient_key,
                    $json['errors'],
                    30
                );
            }

            return $json['valid'] ?? false;
        }

    }

    /**
     * Remote request to Merkulove Host(old server)
     * @param string $purchase_code
     * @return array|WP_Error
     */
    private static function remote_request_merkulove_host(string $purchase_code)
    {
        $url = 'https://merkulove.host/wp-content/plugins/mdp-purchase-validator/src/Merkulove/PurchaseValidator/Validate.php?';
        $url .= 'action=validate&'; // Action.
        $url .= 'plugin=' . Plugin::get_slug() . '&'; // Plugin Name.
        $url .= 'domain=' . wp_parse_url(site_url(), PHP_URL_HOST) . '&'; // Domain Name.
        $url .= 'version=' . Plugin::get_version() . '&'; // Plugin version.
        $url .= 'pid=' . $purchase_code . '&'; // Purchase Code.
        $url .= 'admin_e=' . base64_encode(get_option('admin_email'));

        return wp_remote_get(
            $url,
            [
                'timeout' => 15,
                'headers' => [
                    'Accept' => 'application/json'
                ],
                'sslverify' => (Settings::get_instance()->options['check_ssl'] ?? 'off') === 'on'
            ]
        );
    }

    /**
     * Remote request to Merkulove Host (new server v1)
     * @param string $purchase_code
     * @return array|WP_Error
     */
    private static function remote_request_s1_v1(string $purchase_code)
    {

        return wp_remote_post(
            'https://s1.merkulove.host/api/v1/verify',
            [
                'timeout' => 15,
                'headers' => [
                    'Accept' => 'application/json'
                ],
                'body' => [
                    'id' => READABLER['envato_id'] ?? '',
                    'plugin' => Plugin::get_slug(),
                    'version' => Plugin::get_version(),
                    'pid' => esc_attr($purchase_code),
                    'domain' => base64_encode(site_url()),
                    'email' => base64_encode(get_option('admin_email'))
                ],
                'sslverify' => (Settings::get_instance()->options['check_ssl'] ?? 'off') === 'on'
            ]
        );

    }

    private static function remote_request_v2(string $purchase_code)
    {
        // Get url to request item id
        $route = '/api/v2/verify';

        return wp_remote_post(
            EnvatoItem::$host . $route . '?t=' . time(),
            [
                'headers' => EnvatoItem::get_headers($route),
                'body' => [
                    'id' => READABLER['envato_id'] ?? '',
                    'plugin' => Plugin::get_slug(),
                    'version' => Plugin::get_version(),
                    'pid' => $purchase_code,
                    'domain' => site_url(),
                    'email' => get_option('admin_email') ?? null
                ],
                'sslverify' => (Settings::get_instance()->options['check_ssl'] ?? 'off') === 'on'
            ]
        );
    }

}
