<?php
/**
 * Wizard.php
 *
 * @since      1.0.0
 * @author     alfiopiccione <alfio.piccione@gmail.com>
 * @license    http://opensource.org/licenses/gpl-2.0.php GPL v2
 *
 * Copyright (C) 2025 POP
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

namespace WcElectronInvoice;

use WcElectronInvoice\Admin\Settings\OptionPage;
use function WcElectronInvoice\Functions\filterInput;

if (! defined('ABSPATH')) {
    exit; // Exit if accessed directly.
}

/**
 * Wizard
 */
class Wizard
{
    /**
     * randomCode
     *
     * @param int $length
     *
     * @return int|string
     */
    public static function randomCode(int $length = 16)
    {
        $string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789$*#@!';

        try {
            $cod      = '';
            $maxIndex = strlen($string) - 1;

            for ($i = 0; $i < $length; $i++) {
                $cod .= $string[random_int(0, $maxIndex)];
            }
        } catch (\Exception $e) {
            $cod = time();
        }

        return $cod;
    }

    /**
     * Load
     *
     * @return void
     */
    public function load()
    {
        // init
        $this->init();
        // Include wizard template
        add_action('wc_el_inv-after_settings_form', [$this, 'template']);
        add_action('wp_ajax_wizard_config_get', [$this, 'config']);
    }

    /**
     * init Wizard and redirect to step 1 > (start)
     *
     * @return void
     */
    public function init()
    {
        $uidOption  = (int)get_option('pop_account_user_id', false);
        $licenseKey = OptionPage::init()->getOptions('license_key') ?: null;
        $secretKey  = OptionPage::getK() ?: null;
        // Wizard init redirect
        $step   = filterInput($_GET, 'step', FILTER_UNSAFE_RAW) ?: null;
        $wizard = filterInput($_GET, 'wizard', FILTER_UNSAFE_RAW) ?: null;

        // License exist user exist
        if ($licenseKey && $uidOption) {
            return;
        }

        // No uid? wizard init
        if (! $uidOption) {
            $licenseKey = null;
            $secretKey  = null;
        }

        if (! $licenseKey && ! $secretKey && ! $step && ! $wizard &&
            get_option('pop_plugin_wizard_redirect', false)
        ) {
            delete_option('pop_plugin_wizard_redirect');
            $wizardStep1 = esc_url_raw(add_query_arg([
                'page'   => 'wc_el_inv-options-page',
                'tab'    => 'wizard',
                'wizard' => 'init',
            ], admin_url('/admin.php')));

            wp_redirect($wizardStep1);
            die();
        }
    }

    /**
     * Wizard template
     *
     * @return void
     */
    public function template()
    {
        $tab = filterInput($_GET, 'tab', FILTER_UNSAFE_RAW) ?: null;
        if ('wizard' === $tab) {
            require_once \WcElectronInvoice\Plugin::getPluginDirPath('/inc/wizard.php');
        }
    }

    /**
     * Get user Level
     *
     * @return false|mixed|void
     */
    public static function popGetUserLevel($update = false)
    {
        $current_time = time();
        $cachedLevel  = get_option('pop_user_level');
        $expiration   = get_option('pop_user_level_expiration', 0);

        /**
         * @since 6.0.0
         * Having the user id, means the wizard has been completed.
         *
         * Some time in the future we can get rid of the user id and just check for a license_key.
         * This is just a temporary solution to avoid breaking changes, since the license_key was there even before 6.0.0.
         */
        $uid = (int)get_option('pop_account_user_id', false);
        if (! $uid) {
            // If the user id is not set, we can't get the user level, they have to complete the wizard first.
            return $cachedLevel;
        }

        $licenseKey = \WcElectronInvoice\Admin\Settings\OptionPage::init()->getOptions('license_key');
        if (! $licenseKey) {
            // If the license key is not set, we can't get the user level, they have to complete the wizard first.
            return $cachedLevel;
        }

        if (! $update && $cachedLevel && $expiration > time()) {
            // we have a cached level and it's not expired, also the refresh is not forced.
            return $cachedLevel;
        }

        // If the expiration date is no older than one month (30 days), the cached level is returned.
        $one_month_ago = $current_time - (30 * DAY_IN_SECONDS);
        if (! $update && $cachedLevel && $expiration >= $one_month_ago) {
            return $cachedLevel;
        }

        // make the remote request
        $userLevelResponse = wp_remote_post(WC_EL_INV_POP_API_URL . 'user-level', [
            'timeout' => 3,
            'body'    => json_encode([
                'plugin_version' => WC_EL_INV_VERSION,
                'license_key'    => $licenseKey,
            ]),
            'headers' => [
                'Content-Type' => 'application/json',
                'X-API-Key'    => $licenseKey,
            ],
        ]);

        // handle errors
        if (is_wp_error($userLevelResponse)) {
            $error_message = $userLevelResponse->get_error_message();
            error_log('/user-level API error: ' . $error_message);

            return $cachedLevel;
        }

        // handle bad response
        $responseCode = wp_remote_retrieve_response_code($userLevelResponse);
        if (404 === $responseCode) {
            return $cachedLevel;
        }

        // fetch the body
        $body = wp_remote_retrieve_body($userLevelResponse);
        $data = json_decode($body, true);

        // handle wrong or empty data
        if (empty($data['user_level'])) {
            return $cachedLevel;
        }

        $getSdiPOPIntegrationData = InvoiceApi::getSdiPOPIntegrationData();
        if ('free' === $data['user_level'] && $getSdiPOPIntegrationData->active_integration) {
            delete_option("wc_el_inv-active_sdipop_integration");
            delete_option("wc_el_inv-business_apply_signature");
            delete_option("wc_el_inv-business_apply_legal_storage");
        }

        // update the options
        update_option('pop_user_level', $data['user_level'], false);
        update_option('pop_user_level_expiration', time() + DAY_IN_SECONDS, false);

        return $data['user_level'];
    }

    /**
     * isUserLevelGte
     *
     * @param $level
     * @param $compare
     *
     * @return bool
     */
    public static function isUserLevelGte($level, $compare)
    {
        $levels = ['free', 'basic', 'growth', 'pro', 'enterprise'];

        $levelIndex   = array_search($level, $levels);
        $compareIndex = array_search($compare, $levels);

        return $levelIndex >= $compareIndex;
    }

    /**
     * setLicense
     *
     * @param $license_key
     *
     * @return void
     */
    public function setLicense($license_key)
    {
        // Store license
        $options['wc_el_inv-settings-license_key'] = $license_key;
        $options['wc_el_inv-settings-key']         = $license_key;
        update_option('wc_el_inv_options', $options);

        // Store secret api key
        $secretApiKey = base64_encode(md5($license_key . site_url()));
        $secretApiKey = str_replace('=', '0', $secretApiKey);
        update_option('wc_el_inv-secret-api-key', $secretApiKey);
    }

    /**
     * Wizard config
     *
     * @return void|null
     */
    public function config()
    {
        if (! check_ajax_referer('ajax_wizard_nonce', 'security')) {
            return null;
        }

        $action = filterInput($_POST, 'action', FILTER_UNSAFE_RAW);
        if ('wizard_config_get' !== $action) {
            wp_send_json_error(['message' => esc_html__('Invalid action', WC_EL_INV_TEXTDOMAIN)], 400);
        }

        $license_key = filterInput($_POST, 'license_key', FILTER_UNSAFE_RAW);
        $user_id     = filterInput($_POST, 'user_id', FILTER_UNSAFE_RAW);
        if (! $user_id || ! $license_key) {
            return null;
        }

        $config = $this->updateConfig($license_key);

        if (is_wp_error($config->response)) {
            $error_message = $config->response->get_error_message();
            error_log('method config: configurations API error: ' . $error_message);
            wp_send_json_error([
                'message' => $error_message,
            ], 500);
        }

        $responseCode = wp_remote_retrieve_response_code($config->response);
        $body         = wp_remote_retrieve_body($config->response);
        $data         = json_decode($body, true);

        if (200 === (int)$responseCode) {
            $setDataList = [];
            if (! empty($data['user_data']) && true === $data['user_data']['success']) {
                if (! empty($data['user_data']['configurations'])) {
                    foreach ($data['user_data']['configurations'] as $key => $configuration) {
                        if (! $config->update) {
                            // Store integration provider option
                            update_option("wc_el_inv-{$key}", $configuration);
                        }
                        // Update value
                        $setDataList["wc_el_inv-{$key}"] = get_option("wc_el_inv-{$key}", false);
                    }

                    // Activate the integration inside the plugin the first time after the wizard only if it has been activated in the account
                    if (\WcElectronInvoice\Integrations::isSdiPopIntegrationActive()) {
                        if (get_option('wc_el_inv-addon-sdi-via-pop') === false) {
                            add_option('wc_el_inv-addon-sdi-via-pop', 1);
                        }
                    }
                }

                if (empty($setDataList)) {
                    wp_send_json_error([
                        'message' => esc_html__('Empty data: error saving configuration.', WC_EL_INV_TEXTDOMAIN),
                        'list'    => $setDataList,
                    ], 400);
                }

                // Store account user ID
                update_option('pop_account_user_id', $user_id);

                // Delete cached files
                do_action('wc_el_inv-delete_cached_legal_file');

                // Set license
                $this->setLicense($data['user_data']['license_key']);

                wp_send_json_success([
                    'message'        => esc_html__('Saved configuration.', WC_EL_INV_TEXTDOMAIN),
                    'configurations' => $data['user_data']['configurations'],
                    'setting_data'   => $setDataList,
                    'license_key'    => $data['user_data']['license_key'],
                    'secret_key'     => OptionPage::getK(),
                ], 200);
            } else {
                wp_send_json_error([
                    'message' => esc_html__('Empty data: error saving configuration.', WC_EL_INV_TEXTDOMAIN),
                ], 400);
            }
        } else {
            wp_send_json_error([
                'message' => esc_html__('Response error: code ', WC_EL_INV_TEXTDOMAIN) . $responseCode,
            ], 400);
        }

        if (empty($data)) {
            wp_send_json_error([
                'message' => esc_html__('No data received.', WC_EL_INV_TEXTDOMAIN),
            ], 400);
        }
    }

    /**
     * updateConfig
     *
     * @param $licenseKey
     *
     * @return object
     */
    public function updateConfig($licenseKey = null): object
    {
        if (! $licenseKey) {
            $licenseKey = \WcElectronInvoice\Admin\Settings\OptionPage::init()->getOptions('license_key');
        }
        $response = wp_remote_post(WC_EL_INV_API_DOMAIN . '/wp-json/wp-pop/v1/wizard-config-get', [
            'timeout' => 15,
            'body'    => json_encode([
                'license_key' => $licenseKey,
                'pv'          => esc_attr(WC_EL_INV_VERSION),
            ]),
            'headers' => [
                'Content-Type' => 'application/json',
                'X-API-Key'    => $licenseKey,
            ],
        ]);

        $update     = false;
        $licenseKeyFromConfig = null;

        if (is_wp_error($response)) {
            $error_message = $response->get_error_message();
            error_log('method updateConfig: configurations API error: ' . $error_message);
        } else {
            $responseCode = wp_remote_retrieve_response_code($response);
            $body         = wp_remote_retrieve_body($response);
            $data         = json_decode($body, true);

            if (200 === (int)$responseCode) {
                if (! empty($data['user_data']) && true === $data['user_data']['success']) {
                    if (! empty($data['user_data']['configurations'])) {
                        error_log('method updateConfig: config update ' . print_r($data, true));
                        $licenseKeyFromConfig = $data['user_data']['license_key'];
                        foreach ($data['user_data']['configurations'] as $key => $configuration) {
                            // Store integration provider option
                            update_option("wc_el_inv-{$key}", $configuration);
                            $update = true;
                        }

                        // Activate the integration inside the plugin the first time after the wizard only if it has been activated in the account
                        if (\WcElectronInvoice\Integrations::isSdiPopIntegrationActive()) {
                            if (get_option('wc_el_inv-addon-sdi-via-pop') === false) {
                                add_option('wc_el_inv-addon-sdi-via-pop', 1);
                            }
                        }
                    }

                    // Fetch and store user level
                    \WcElectronInvoice\Wizard::popGetUserLevel(true);
                    // Update allowed addon
                    Plugin::allowedAddon(true);

                    // Delete cached files
                    do_action('wc_el_inv-delete_cached_legal_file');
                }
            } else {
                error_log('method updateConfig: response error code' . $responseCode);
            }
        }

        return (object)array(
            'response'    => $response,
            'license_key' => $licenseKeyFromConfig,
            'update'      => $update,
        );
    }
}
