<?php
/**
 * Class WCVendors_Pro_Admin_License
 *
 * This class handles the license management functionality for the WC Vendors Pro plugin in the admin area.
 */
class WCVendors_Pro_Admin_License {

    /**
     * License data
     *
     * @since 1.9.0
     *
     * @var array $license_data The license data.
     */
    private $license_data;

    /**
     * Server URL
     *
     * @since 1.9.0
     *
     * @var string $server_url The server URL.
     */
    private $server_url = '';

    /**
     * Software key
     *
     * @since 1.9.0
     *
     * @var array $software_key The software key.
     */
    private $software_key = 'WCVP';

    /**
     * Instance of this class.
     *
     * @var object $instance The instance of this class.
     */
    protected static $instance = null;

    /**
     * Plugin file
     *
     * @var string $plugin_file The plugin file.
     */
    private $plugin_file;

    /**
     * License options key
     *
     * @var string $license_option_key The license options key.
     */
    private $license_option_key = 'wc-vendors-pro_license_manager';

    /**
     * Get instance of this class.
     *
     * @param string $plugin_file The plugin file.
     *
     * @return object The instance of this class.
     */
    public static function get_instance( $plugin_file ) {
        if ( null === self::$instance ) {
            self::$instance = new self( $plugin_file );
        }
        return self::$instance;
    }

    /**
     * Constructor.
     *
     * @param string $plugin_file The plugin file.
     *
     * @since 1.9.0
     */
    public function __construct( $plugin_file = '' ) {
        $this->server_url     = defined( 'WCV_LICENSE_SERVER' ) ? WCV_LICENSE_SERVER : '';
        $this->plugin_file    = $plugin_file;
        $default_license_data = array(
            'license_key'            => '',
            'license_email'          => '',
            'license_status'         => '',
            'license_expires'        => '',
            'max_activation'         => '',
            'max_staging_activation' => '',
            'current_version'        => '',
        );
        $this->license_data   = is_multisite() ? get_site_option( $this->license_option_key, array() ) : get_option( $this->license_option_key, array() );
        $this->license_data   = wp_parse_args( $this->license_data, $default_license_data );
        add_filter( 'wcvendors_pro_license_page_content', array( $this, 'output_license_page_content' ) );
        add_action( 'wcvendors_pro_before_license_page_content', array( $this, 'output_before_license_page_content' ), 15 );
        add_filter( 'wp_kses_allowed_html', array( $this, 'wcv_pro_admin_allowed_html' ), 10, 2 );
        add_filter( 'wcvendors_pro_current_plan_status_html', '__return_empty_string' );
        add_action( 'admin_enqueue_scripts', array( $this, 'include_js' ) );
        add_filter( 'wcvendors_license_page_plugins', array( $this, 'change_pro_title' ) );
        add_action( 'wp_ajax_wcvp_activate_license', array( $this, 'activate_license' ) );
        add_action( 'wp_ajax_wcvp_dismiss_notice', array( $this, 'dismiss_license_notice' ) );
        add_action( 'admin_notices', array( $this, 'output_license_notice' ) );
    }

    /**
     * Get license prop
     *
     * @param string $prop The license prop to get.
     * @since 1.9.0
     * @return mixed The license prop.
     */
    public function get_license_prop( $prop ) {
        return isset( $this->license_data[ $prop ] ) ? $this->license_data[ $prop ] : '';
    }

    /**
     * Outputs the content of the license page.
     *
     * @since 1.9.0
     *
     * @return string The content of the license page.
     */
    public function output_license_page_content() {
        $license_email  = $this->get_license_prop( 'license_email' );
        $license_status = $this->get_license_prop( 'license_status' );
        $license_key    = $this->get_license_prop( 'license_key' );
        $button_text    = __( 'Activate', 'wcvendors-pro' );
        ob_start();
        include 'views/license/html-license-section.php';
        $content = ob_get_clean();
        return $content;
    }

    /**
     * Is license expired
     *
     * @since 1.9.0
     * @return bool True if the license is expired, false otherwise.
     */
    public function is_license_expired() {
        $license_status = $this->get_license_prop( 'license_status' );
        $expires        = $this->get_license_prop( 'license_expires' );
        $now            = new DateTime();
        $expires        = new DateTime( $expires );
        $is_expired     = $now > $expires;
        return 'expiring' === $license_status || $is_expired || 'expired' === $license_status;
    }

    /**
     * Checks if the license is activated.
     *
     * @since 1.9.0
     *
     * @return bool True if the license is activated, false otherwise.
     */
    public function is_license_activated() {
        $license_status = $this->get_license_prop( 'license_status' );
        return 'active' === $license_status;
    }


    /**
     * Modifies the allowed HTML tags for the WCV Pro admin.
     *
     * @since 1.9.0
     *
     * @param array  $allowed_html The original set of allowed HTML tags.
     * @param string $context      The current context.
     *
     * @return array The modified set of allowed HTML tags.
     */
    public function wcv_pro_admin_allowed_html( $allowed_html, $context ) {

        if ( is_admin() && 'post' === $context ) {
            $allowed_html = array_merge(
                $allowed_html,
                array(
                    'input'  => array(
                        'type'        => true,
                        'name'        => true,
                        'id'          => true,
                        'value'       => true,
                        'required'    => true,
                        'class'       => true,
                        'style'       => true,
                        'placeholder' => true,
                    ),
                    'label'  => array(
                        'for'   => true,
                        'width' => true,
                    ),
                    'button' => array(
                        'class' => true,
                        'id'    => true,
                    ),
                    'table'  => array(
                        'style' => true,
                        'width' => true,
                    ),
                    'form'   => array(
                        'method' => true,
                        'id'     => true,
                    ),
                )
            );
        }

        return $allowed_html;
    }
    /**
     * Outputs content before the license page content.
     *
     * @since 1.9.0
     *
     * @return void
     */
    public function output_before_license_page_content() {
        $license_status = $this->get_license_prop( 'license_status' ) ? $this->get_license_prop( 'license_status' ) : 'inactive';

        $expires     = $this->get_license_prop( 'license_expires' );
        $status_text = array(
            'active'                          => array(
                'color' => 'color-green',
                'text'  => esc_html__( 'Active', 'wcvendors-pro' ),
            ),
            'expired'                         => array(
                'color' => 'color-red',
                'text'  => esc_html__( 'Expired', 'wcvendors-pro' ) . ' (' . esc_html( $expires ) . ')',
            ),
            'inactive'                        => array(
                'color' => 'color-red',
                'text'  => esc_html__( 'Inactive', 'wcvendors-pro' ),
            ),
            'invalid'                         => array(
                'color' => 'color-red',
                'text'  => esc_html__( 'Invalid', 'wcvendors-pro' ),
            ),
            'disabled'                        => array(
                'color' => 'color-red',
                'text'  => esc_html__( 'Disabled', 'wcvendors-pro' ),
            ),
            'expiring'                        => array(
                'color' => 'color-orange',
                'text'  => esc_html__( 'Expiring', 'wcvendors-pro' ),
            ),
            'max_staging_activations_reached' => array(
                'color' => 'color-red',
                'text'  => __( 'Max Staging Activations Reached', 'wcvendors-pro' ),
            ),
        );

        $status_text_text  = isset( $status_text[ $license_status ]['text'] ) ? $status_text[ $license_status ]['text'] : '';
        $status_text_color = isset( $status_text[ $license_status ]['color'] ) ? $status_text[ $license_status ]['color'] : '#000000';
        echo '<div class="wcv-form-row">';
        echo '<div class="wcv-form-row-full">';
        printf(
            '<p>%s<br><strong>%s</strong> %s</p>',
            esc_html__( 'You are currently using WC Vendors Pro', 'wcvendors-pro' ),
            esc_html__( 'Version:', 'wcvendors-pro' ),
            esc_html( WCV_PRO_VERSION )
        );
        echo '</div>';
        echo '<div class="wcv-form-row-full">';
        printf(
            '<p><strong>%s</strong> <span class="%s license_status">%s</span></p>',
            esc_html__( 'License Status:', 'wcvendors-pro' ),
            esc_attr( $status_text_color ),
            esc_html( $status_text_text )
        );
        echo '</div>';
        echo '</div>';
    }

    /**
     * Include JS for the license page.
     *
     * @since 1.9.0
     * @return void
     */
    public function include_js() {
        $nonce            = wp_create_nonce( 'wcvendors_license_nonce' );
        $admin_assets_url = plugin_dir_url( $this->plugin_file ) . 'admin/assets/';
        $suffix           = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
        $action_type      = 'wcvp_activate_license';
        $i18n             = array(
            'active'   => __( 'Active', 'wcvendors-pro' ),
            'inactive' => __( 'Inactive', 'wcvendors-pro' ),
            'disabled' => __( 'Disabled', 'wcvendors-pro' ),
            'invalid'  => __( 'Invalid', 'wcvendors-pro' ),
            'activate' => __( 'Activate', 'wcvendors-pro' ),
            'expires'  => __( 'Expires', 'wcvendors-pro' ),
            'expired'  => __( 'Expired', 'wcvendors-pro' ),
            'error'    => __( 'An error occurred, please try again!', 'wcvendors-pro' ),
        );
        wp_enqueue_script( 'wcv-pro-license', $admin_assets_url . 'js/wcvendors-pro-license' . $suffix . '.js', array( 'jquery' ), WCV_PRO_VERSION, true );
        wp_localize_script(
            'wcv-pro-license',
            'wcvProLicense',
            array(
                'nonce'  => $nonce,
                'action' => $action_type,
                'i18n'   => $i18n,
            )
        );
    }

    /**
     * Change the title of the pro plugin.
     *
     * @param array $plugins The array of plugins.
     *
     * @since 1.9.0
     * @return array The modified array of plugins.
     */
    public function change_pro_title( $plugins ) {
        $plugins['wcvendors_pro']['title'] = __( 'WC Vendors Pro', 'wcvendors-pro' );
        return $plugins;
    }

    /**
     * Ajax action to activate the license.
     *
     * @since 1.9.0
     * @return mixed The response.
     */
    public function activate_license() {
        $license_key   = isset( $_POST['license_key'] ) ? sanitize_text_field( wp_unslash( $_POST['license_key'] ) ) : '';
        $license_email = isset( $_POST['license_email'] ) ? sanitize_email( wp_unslash( $_POST['license_email'] ) ) : '';
        $nonce         = isset( $_POST['wcvendors_license_nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['wcvendors_license_nonce'] ) ) : '';

        if ( ! wp_verify_nonce( $nonce, 'wcvendors_license_nonce' ) ) {
            wp_send_json_error( array( 'message' => esc_html__( 'Invalid nonce', 'wcvendors-pro' ) ) );
        }

        if ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) {
            wp_send_json_error( array( 'message' => esc_html__( 'Invalid request', 'wcvendors-pro' ) ) );
        }

        if ( empty( $license_key ) || empty( $license_email ) ) {
            wp_send_json_error(
                array(
                    'message' => esc_html__( 'Please enter a valid license key and email', 'wcvendors-pro' ),
                )
            );
        }

        $response = $this->make_request(
            'activate',
            array(
                'license_key'      => $license_key,
                'activation_email' => $license_email,
            )
        );

        if ( is_wp_error( $response ) ) {
            wp_send_json_error(
                array(
                    'message' => $response->get_error_message(),
                )
            );
        }

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

        if ( isset( $license_data['license_status'] ) && 'invalid' === $license_data['license_status'] ) {
            $license_data['license_status'] = 'inactive';
        }

        $new_license_data = array(
            'license_key'            => $license_key,
            'license_email'          => $license_email,
            'license_status'         => isset( $license_data['license_status'] ) ? $license_data['license_status'] : '',
            'license_expires'        => isset( $license_data['expiration_timestamp'] ) ? $license_data['expiration_timestamp'] : '',
            'max_activation'         => isset( $license_data['max_activation'] ) ? $license_data['max_activation'] : '',
            'max_staging_activation' => isset( $license_data['max_staging_activation'] ) ? $license_data['max_staging_activation'] : '',
            'current_version'        => WCV_PRO_VERSION,
        );

        $this->update_license_data( $new_license_data );
        $message_key = array( 'message', 'error_msg', 'success_msg' );
        $message     = '';
        foreach ( $message_key as $key ) {
            if ( isset( $license_data[ $key ] ) ) {
                $message = $license_data[ $key ];
                break;
            }
        }

        $expires = isset( $license_data['expiration_timestamp'] ) ? $license_data['expiration_timestamp'] : '';
        wp_send_json_success(
            array(
                'message'       => $message,
                'status'        => $license_data['status'],
                'licenseStatus' => isset( $license_data['license_status'] ) ? $license_data['license_status'] : '',
                'expires'       => $expires,
            )
        );

        wp_die();
    }

    /**
     * Dismiss the license notice.
     *
     * @since 1.9.0
     * @return void
     */
    public function dismiss_license_notice() {
        $nonce = isset( $_POST['wcvendors_license_nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['wcvendors_license_nonce'] ) ) : '';

        if ( ! wp_verify_nonce( $nonce, 'wcvendors_license_nonce' ) ) {
            wp_send_json_error( array( 'message' => esc_html__( 'Invalid nonce', 'wcvendors-pro' ) ) );
        }

        if ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) {
            wp_send_json_error( array( 'message' => esc_html__( 'Invalid request', 'wcvendors-pro' ) ) );
        }

        if ( is_multisite() ) {
            update_site_option( 'wcvendors_pro_license_notice_dismissed', 'yes' );
        } else {
            update_option( 'wcvendors_pro_license_notice_dismissed', 'yes' );
        }

        wp_send_json_success( array( 'message' => esc_html__( 'Notice dismissed', 'wcvendors-pro' ) ) );
        wp_die();
    }

    /**
     * Make a request to the license server.
     *
     * @param string $action The action to perform.
     * @param array  $args   The arguments to send.
     *
     * @since 1.9.0
     * @return mixed The response.
     */
    public function make_request( $action, $args ) {
        $enpoint = $this->server_url . '/wp-json/slmw/v1/license/' . $action;

        $default_args = array(
            'software_key' => $this->software_key,
            'version'      => WCV_PRO_VERSION,
            'site_url'     => home_url(),
            'is_multisite' => is_multisite() ? 1 : 0,
        );

        $args     = wp_parse_args( $args, $default_args );
        $response = wp_remote_post(
            $enpoint,
            array(
                'body' => $args,
            )
        );

        return $response;
    }

    /**
     * Update license data.
     *
     * @param array $license_data The license data.
     *
     * @since 1.9.0
     */
    public function update_license_data( $license_data ) {
        $current_license_data = $this->license_data;
        if ( ! is_array( $current_license_data ) ) {
            $current_license_data = array();
        }
        $new_license_data = array_merge( $current_license_data, $license_data );
        if ( is_multisite() ) {
            update_site_option( $this->license_option_key, $new_license_data );
        } else {
            update_option( $this->license_option_key, $new_license_data );
        }
    }

    /**
     * Output the license notice.
     *
     * @since 1.9.0
     * @return void
     */
    public function output_license_notice() {
        $is_dismissed = is_multisite() ? get_site_option( 'wcvendors_pro_license_notice_dismissed', 'no' ) : get_option( 'wcvendors_pro_license_notice_dismissed', 'no' );
        if ( $this->is_license_activated() || wc_string_to_bool( $is_dismissed ) ) {
            return;
        }
        $active_page_url = admin_url( 'admin.php?page=wc-vendors-license&tab=wcvendors_pro' );
        include 'views/notices/html-notice-license-check.php';
    }
}
