<?php
/**
 * Setup wizard loader and AJAX handlers.
 *
 * @package Noesia_Smart_Waiter
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

if ( ! class_exists( 'Noesia_SWA_Setup_Wizard' ) ) {
    /**
     * Handles the Smart Waiter setup wizard shell.
     */
    class Noesia_SWA_Setup_Wizard {

        /**
         * Target top-level admin hook.
         *
         * @var string
         */
        private $target_hook = 'toplevel_page_noesia_swa_settings';

        /**
         * User meta key for wizard state.
         *
         * @var string
         */
        private $state_meta_key = 'noesia_swa_setup_wizard_state_v1';

        /**
         * User meta key for wizard interface preferences.
         *
         * @var string
         */
        private $prefs_meta_key = 'noesia_swa_setup_wizard_prefs_v1';

        /**
         * Cookie name for manual-only wizard mode.
         *
         * @var string
         */
        private $manual_only_cookie = 'noesia_swa_wizard_manual_only';

        /**
         * Cookie lifetime in days.
         *
         * @var int
         */
        private $manual_only_days = 365;

        /**
         * Constructor.
         */
        public function __construct() {
            add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ), 1 );
            add_action( 'admin_footer', array( $this, 'render_shell' ), 1 );
            add_action( 'wp_ajax_noesia_swa_wizard_state', array( $this, 'handle_state_request' ) );
            add_action( 'wp_ajax_noesia_swa_wizard_preferences', array( $this, 'handle_preferences_request' ) );
        }

        /**
         * Enqueue wizard assets only on the Smart Waiter shell screen.
         *
         * @param string $hook Current admin page hook.
         * @return void
         */
        public function enqueue_assets( $hook ) {
            if ( ! $this->is_target_screen( $hook ) || ! current_user_can( 'manage_options' ) ) {
                return;
            }

            wp_enqueue_style(
                'noesia-swa-wizard-css',
                NOESIA_SWA_PLUGIN_URL . 'admin/wizard/css/noesia-wizard.css',
                array(),
                NOESIA_SWA_VERSION
            );

            wp_enqueue_script(
                'noesia-swa-wizard-js',
                NOESIA_SWA_PLUGIN_URL . 'admin/wizard/js/noesia-wizard.js',
                array(),
                NOESIA_SWA_VERSION,
                true
            );

            wp_localize_script(
                'noesia-swa-wizard-js',
                'noesiaSwaWizardVars',
                array(
                    'ajaxUrl'            => admin_url( 'admin-ajax.php' ),
                    'nonce'              => wp_create_nonce( 'noesia_swa_wizard_nonce' ),
                    'coreNonce'          => wp_create_nonce( 'noesia_swa_nonce' ),
                    'settingsUrl'        => $this->get_settings_url(),
                    'status'             => $this->get_wizard_status(),
                    'autoOpen'           => $this->should_auto_open(),
                    'manualOnlyCookie'   => $this->manual_only_cookie,
                    'manualOnlyDays'     => $this->manual_only_days,
                    'preferences'        => $this->get_user_preferences(),
                    'defaultPreferences' => $this->get_default_preferences(),
                    'diagnostics'        => $this->get_diagnostics_payload(),
                    'storage'            => array(
                        'wizardState' => 'noesia_swa_setup_wizard_state_v1',
                        'menuMode'    => 'noesia_swa_menu_mode',
                        'navStyle'    => 'noesia_swa_nav_style',
                        'geminiMode'  => 'noesia_swa_gemini_sidebar_mode',
                        'quickDock'   => 'noesia_swa_quick_dock_open',
                    ),
                    'strings'            => array(
                        'saving'                  => __( 'Saving...', 'noesia-smart-waiter' ),
                        'saveFailed'              => __( 'The wizard could not save your latest change. Please try again.', 'noesia-smart-waiter' ),
                        'settingsLabel'           => __( 'Settings', 'noesia-smart-waiter' ),
                        'untitledModule'          => __( 'Module', 'noesia-smart-waiter' ),
                        'menuSaved'               => __( 'Menu Box Manager updated.', 'noesia-smart-waiter' ),
                        'manualOnlyTitle'         => __( 'Don’t show again', 'noesia-smart-waiter' ),
                        'manualOnlyText'          => __( 'Open this wizard only manually from the Smart Waiter header button.', 'noesia-smart-waiter' ),
                        'diagnosticsInit'         => __( 'Initializing Matrix Protocol...', 'noesia-smart-waiter' ),
                        'diagnosticsJs'           => __( 'JavaScript Runtime', 'noesia-smart-waiter' ),
                        'diagnosticsCookies'      => __( 'Cookie Support', 'noesia-smart-waiter' ),
                        'diagnosticsStorage'      => __( 'Local Storage Access', 'noesia-smart-waiter' ),
                        'diagnosticsBrowser'      => __( 'Browser Engine', 'noesia-smart-waiter' ),
                        'diagnosticsWordPress'    => __( 'WordPress Core Status', 'noesia-smart-waiter' ),
                        'diagnosticsMemory'       => __( 'Server Memory Profile', 'noesia-smart-waiter' ),
                        'diagnosticsRest'         => __( 'REST API Layer', 'noesia-smart-waiter' ),
                        'diagnosticsKernel'       => __( 'NOESIA MATRIX KERNEL', 'noesia-smart-waiter' ),
                        'diagnosticsComplete'     => __( 'DIAGNOSTICS COMPLETE.', 'noesia-smart-waiter' ),
                        'diagnosticsChromeHint'   => __( 'Chrome is recommended for optimal performance.', 'noesia-smart-waiter' ),
                        'diagnosticsUnavailable'  => __( 'Unavailable', 'noesia-smart-waiter' ),
                        'diagnosticsHttpStatus'   => __( 'HTTP', 'noesia-smart-waiter' ),
                    ),
                )
            );
        }

        /**
         * Render the wizard shell after the admin page markup.
         *
         * @return void
         */
        public function render_shell() {
            if ( ! $this->is_target_screen() || ! current_user_can( 'manage_options' ) ) {
                return;
            }

            $context = array(
                'logo_url'      => esc_url( NOESIA_SWA_PLUGIN_URL . 'admin/wizard/images/noesia-logo.png' ),
                'settings_url'  => esc_url( $this->get_settings_url() ),
                'wizard_status' => $this->should_auto_open() ? 'pending' : 'skipped',
                'payload'       => $this->build_shell_payload(),
            );

            require NOESIA_SWA_PLUGIN_DIR . 'admin/wizard/views/wizard-shell.php';
        }

        /**
         * Handle wizard completion / skip state persistence.
         *
         * @return void
         */
       public function handle_state_request() {
	if ( ! current_user_can( 'manage_options' ) ) {
		wp_send_json_error(
			array(
				'message' => __( 'You are not allowed to do that.', 'noesia-smart-waiter' ),
			),
			403
		);
	}

	if ( ! $this->is_valid_wizard_request() ) {
		wp_send_json_error(
			array(
				'message' => __( 'Your wizard session expired. Please refresh and try again.', 'noesia-smart-waiter' ),
			),
			403
		);
	}

	$status = $this->get_sanitized_post_key( 'status' );
	$status = in_array( $status, array( 'pending', 'completed', 'skipped' ), true ) ? $status : 'pending';

	$state = array(
		'status'       => $status,
		'updated_at'   => current_time( 'mysql' ),
		'version'      => NOESIA_SWA_VERSION,
		'completed_at' => in_array( $status, array( 'completed', 'skipped' ), true ) ? current_time( 'mysql' ) : '',
	);

	update_user_meta( get_current_user_id(), $this->state_meta_key, $state );

	wp_send_json_success(
		array(
			'status' => $status,
			'state'  => $state,
		)
	);
}

        /**
         * Handle wizard interface preference persistence.
         *
         * @return void
         */
        public function handle_preferences_request() {
	if ( ! current_user_can( 'manage_options' ) ) {
		wp_send_json_error(
			array(
				'message' => __( 'You are not allowed to do that.', 'noesia-smart-waiter' ),
			),
			403
		);
	}

	if ( ! $this->is_valid_wizard_request() ) {
		wp_send_json_error(
			array(
				'message' => __( 'Your wizard session expired. Please refresh and try again.', 'noesia-smart-waiter' ),
			),
			403
		);
	}

	$defaults = $this->get_default_preferences();
	$prefs    = array(
		'nav_style'    => $this->get_posted_nav_style( $defaults['nav_style'] ),
		'dock_enabled' => $this->is_posted_dock_enabled( $defaults['dock_enabled'] ) ? '1' : '0',
		'updated_at'   => current_time( 'mysql' ),
	);

	update_user_meta( get_current_user_id(), $this->prefs_meta_key, $prefs );

	wp_send_json_success(
		array(
			'preferences' => $prefs,
		)
	);
}

        /**
         * Validate wizard AJAX requests with nonce-first logic and a safe admin referer fallback.
         *
         * @return bool
         */
        private function is_valid_wizard_request() {
	$request_method = isset( $_SERVER['REQUEST_METHOD'] )
		? strtoupper( sanitize_text_field( wp_unslash( (string) $_SERVER['REQUEST_METHOD'] ) ) )
		: '';

	if ( 'POST' !== $request_method ) {
		return false;
	}

	// phpcs:ignore WordPress.Security.NonceVerification.Missing -- This helper reads the AJAX nonce only to verify the request before any mutation is processed.
	if ( ! isset( $_POST['nonce'] ) ) {
		return false;
	}

	// phpcs:ignore WordPress.Security.NonceVerification.Missing -- This helper reads the AJAX nonce only to verify the request before any mutation is processed.
	$nonce = sanitize_text_field( wp_unslash( (string) $_POST['nonce'] ) );

	if ( '' === $nonce ) {
		return false;
	}

	return false !== wp_verify_nonce( $nonce, 'noesia_swa_wizard_nonce' );
}


        /**
         * Get the posted wizard navigation style or the provided default.
         *
         * @param string $default_nav_style Default navigation style.
         * @return string
         */
        private function get_posted_nav_style( $default_nav_style ) {
            $nav_style = $this->get_unslashed_post_value( 'nav_style' );

            if ( ! is_string( $nav_style ) || '' === $nav_style ) {
                return $default_nav_style;
            }

            return $this->sanitize_nav_style( $nav_style );
        }

        /**
         * Determine the posted wizard dock preference.
         *
         * @param string $default_dock_enabled Default dock flag.
         * @return bool
         */
        private function is_posted_dock_enabled( $default_dock_enabled ) {
            $dock_raw = $this->get_unslashed_post_value( 'dock_enabled' );
            $dock_raw = is_scalar( $dock_raw ) || null === $dock_raw ? $dock_raw : $default_dock_enabled;

            if ( null === $dock_raw || '' === (string) $dock_raw ) {
                $dock_raw = $default_dock_enabled;
            }

            return ! in_array( strtolower( (string) $dock_raw ), array( '0', 'false', 'off', 'no' ), true );
        }


        /**
         * Read an unslashed scalar POST value after a verified wizard request.
         *
         * @param string $key POST field name.
         * @return string|null
         */
        private function get_unslashed_post_value( $key ) {
	$request_key = sanitize_key( $key );

	if ( '' === $request_key ) {
		return null;
	}

	// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Wizard handlers verify the AJAX nonce before reading scalar POST fields through this helper.
	if ( ! isset( $_POST[ $request_key ] ) ) {
		return null;
	}

	// phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Wizard handlers verify the AJAX nonce before reading scalar POST fields; scalar values are sanitized before being returned.
$value = wp_unslash( $_POST[ $request_key ] );

	if ( ! is_scalar( $value ) ) {
		return null;
	}

	return sanitize_text_field( (string) $value );
}

        /**
         * Read and sanitize a scalar POST key.
         *
         * @param string $key POST field name.
         * @return string
         */
        private function get_sanitized_post_key( $key ) {
            $value = $this->get_unslashed_post_value( $key );

            if ( ! is_string( $value ) ) {
                return '';
            }

            return sanitize_key( $value );
        }

        /**
         * Build the rendered shell payload.
         *
         * @return array<string,mixed>
         */
        private function build_shell_payload() {
            return array(
                'status'              => $this->get_wizard_status(),
                'modules'             => $this->get_module_cards(),
                'hidden_sections'     => $this->get_hidden_sections(),
                'preferences'         => $this->get_user_preferences(),
                'default_preferences' => $this->get_default_preferences(),
                'style_previews'      => $this->get_style_previews(),
                'dock_preview'        => NOESIA_SWA_PLUGIN_URL . 'admin/wizard/images/dock-preview.png',
                'settings_url'        => $this->get_settings_url(),
                'settings_section'    => 'settings',
                'menu_action'         => 'noesia_swa_save_menu_state',
            );
        }

        /**
         * Get wizard completion status.
         *
         * @return string
         */
        private function get_wizard_status() {
            $raw = get_user_meta( get_current_user_id(), $this->state_meta_key, true );

            if ( is_array( $raw ) && ! empty( $raw['status'] ) ) {
                $status = sanitize_key( (string) $raw['status'] );
                if ( in_array( $status, array( 'pending', 'completed', 'skipped' ), true ) ) {
                    return $status;
                }
            }

            return 'pending';
        }

        /**
         * Determine whether the wizard should auto-open for the current request.
         *
         * @return bool
         */
        private function should_auto_open() {
            if ( empty( $_COOKIE[ $this->manual_only_cookie ] ) ) {
                return true;
            }

            $cookie_value = sanitize_text_field( wp_unslash( (string) $_COOKIE[ $this->manual_only_cookie ] ) );

            return '1' !== $cookie_value;
        }

        /**
         * Get saved wizard preferences.
         *
         * @return array<string,mixed>
         */
        private function get_user_preferences() {
            $saved    = get_user_meta( get_current_user_id(), $this->prefs_meta_key, true );
            $defaults = $this->get_default_preferences();

            $prefs = array(
                'nav_style'      => $defaults['nav_style'],
                'dock_enabled'   => $defaults['dock_enabled'],
                'has_nav_style'  => false,
                'has_dock_state' => false,
            );

            if ( is_array( $saved ) ) {
                if ( isset( $saved['nav_style'] ) ) {
                    $prefs['nav_style']     = $this->sanitize_nav_style( $saved['nav_style'] );
                    $prefs['has_nav_style'] = true;
                }

                if ( isset( $saved['dock_enabled'] ) ) {
                    $prefs['dock_enabled']   = in_array( strtolower( (string) $saved['dock_enabled'] ), array( '1', 'true', 'on', 'yes' ), true ) ? '1' : '0';
                    $prefs['has_dock_state'] = true;
                }
            }

            return $prefs;
        }

        /**
         * Get default wizard preferences.
         *
         * @return array<string,string>
         */
        private function get_default_preferences() {
            return array(
                'nav_style'    => 'hub',
                'dock_enabled' => '1',
            );
        }

        /**
         * Build module cards from the live admin registry.
         *
         * @return array<int,array<string,mixed>>
         */
        private function get_module_cards() {
            $cards    = array();
            $registry = null;

            if ( function_exists( 'noesia_swa' ) ) {
                $plugin = noesia_swa();
                if ( is_object( $plugin ) && isset( $plugin->admin_sections ) && $plugin->admin_sections instanceof Noesia_SWA_Admin_Sections ) {
                    $registry = $plugin->admin_sections;
                }
            }

            if ( ! $registry instanceof Noesia_SWA_Admin_Sections ) {
                return $cards;
            }

            $hidden_map = array_fill_keys( $this->get_hidden_sections(), true );

            foreach ( $registry->get_nav_items() as $section_id => $section ) {
                $section_id = sanitize_key( (string) $section_id );

                if ( '' === $section_id || 'settings' === $section_id ) {
                    continue;
                }

                if ( ! empty( $section['nav_label'] ) ) {
                    $title = sanitize_text_field( (string) $section['nav_label'] );
                } elseif ( ! empty( $section['label'] ) ) {
                    $title = sanitize_text_field( (string) $section['label'] );
                } else {
                    $title = ucfirst( str_replace( '-', ' ', $section_id ) );
                }

                $cards[] = array(
                    'id'      => $section_id,
                    'title'   => $title,
                    'sub'     => isset( $section['nav_sub'] ) ? sanitize_text_field( (string) $section['nav_sub'] ) : '',
                    'icon'    => isset( $section['icon'] ) ? sanitize_html_class( (string) $section['icon'] ) : '',
                    'tier'    => isset( $section['tier'] ) ? sanitize_key( (string) $section['tier'] ) : 'free',
                    'enabled' => ! isset( $hidden_map[ $section_id ] ),
                );
            }

            return $cards;
        }

        /**
         * Build live diagnostics payload.
         *
         * @return array<string,mixed>
         */
        private function get_diagnostics_payload() {
            global $wp_version;

            $wp_version = is_string( $wp_version ) ? trim( $wp_version ) : '';
            $memory     = '';

            if ( defined( 'WP_MEMORY_LIMIT' ) && is_string( WP_MEMORY_LIMIT ) && '' !== trim( WP_MEMORY_LIMIT ) ) {
                $memory = trim( WP_MEMORY_LIMIT );
            }

            if ( '' === $memory ) {
                $ini_memory = ini_get( 'memory_limit' );
                if ( is_string( $ini_memory ) ) {
                    $memory = trim( $ini_memory );
                }
            }

            return array(
                'wp_version'   => $wp_version,
                'memory_limit' => $memory,
                'rest_url'     => esc_url_raw( rest_url( '/' ) ),
                'kernel_ready' => ! empty( $this->get_module_cards() ),
            );
        }

        /**
         * Read hidden sections from the shared plugin option.
         *
         * @return array<int,string>
         */
        private function get_hidden_sections() {
            $options = get_option( 'noesia_swa_options', array() );

            if ( ! is_array( $options ) ) {
                $options = array();
            }

            if ( empty( $options['menu_hidden_sections'] ) ) {
                return array();
            }

            $decoded = json_decode( (string) $options['menu_hidden_sections'], true );

            if ( ! is_array( $decoded ) ) {
                return array();
            }

            return array_values(
                array_unique(
                    array_filter(
                        array_map( 'sanitize_key', $decoded )
                    )
                )
            );
        }

        /**
         * Determine whether the current request is the Smart Waiter admin screen.
         *
         * @param string|null $hook Optional hook from admin_enqueue_scripts.
         * @return bool
         */
        private function is_target_screen( $hook = null ) {
            $hook = is_string( $hook ) ? $hook : '';

            if ( '' !== $hook ) {
                return $this->target_hook === $hook;
            }

            if ( ! function_exists( 'get_current_screen' ) ) {
                return false;
            }

            $screen = get_current_screen();

            return $screen && isset( $screen->id ) && $this->target_hook === (string) $screen->id;
        }

        /**
         * Get the real plugin settings URL.
         *
         * @return string
         */
        private function get_settings_url() {
            $url = menu_page_url( 'noesia_swa_settings', false );

            if ( ! is_string( $url ) || '' === $url ) {
                $url = admin_url( 'admin.php?page=noesia_swa_settings' );
            }

            return add_query_arg( 'section', 'settings', $url );
        }

        /**
         * Sanitize one nav style preference.
         *
         * @param mixed $value Raw style.
         * @return string
         */
        private function sanitize_nav_style( $value ) {
            $style = sanitize_key( (string) $value );

            if ( ! in_array( $style, array( 'hub', 'titan', 'gemini' ), true ) ) {
                $style = 'hub';
            }

            return $style;
        }

        /**
         * Build wizard preview image map.
         *
         * @return array<string,string>
         */
        private function get_style_previews() {
            return array(
                'gemini' => NOESIA_SWA_PLUGIN_URL . 'admin/wizard/images/gemini-preview.png',
                'titan'  => NOESIA_SWA_PLUGIN_URL . 'admin/wizard/images/titan-preview.png',
                'hub'    => NOESIA_SWA_PLUGIN_URL . 'admin/wizard/images/hub-preview.png',
            );
        }
    }
}
