<?php
/**
 * Interface d'administration.
 *
 * @package PCC
 * @license GPL-2.0-or-later
 */

defined( 'ABSPATH' ) || exit;

class PCC_Admin {

	const FALLBACK_SLUG = 'php-compatibility-checker-by-volade';

	const USER_META_INTRO_COLLAPSED = 'pcc_intro_collapsed';

	/** @var PCC_Plugin */
	private $plugin;

	public function __construct( PCC_Plugin $plugin ) {
		$this->plugin = $plugin;

		add_action( 'volade_register_plugins', array( $this, 'register_volade_menu' ), 10 );
		add_action( 'plugins_loaded', array( $this, 'register_volade_menu' ), 5 );
		add_action( 'admin_menu', array( $this, 'register_menu' ), 11 );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );

		add_action( 'admin_post_pcc_apply_preset', array( $this, 'handle_apply_preset' ) );
		add_action( 'admin_post_pcc_export_report', array( $this, 'handle_export_report' ) );
		add_action( 'admin_post_pcc_export_csv', array( $this, 'handle_export_csv' ) );
		add_action( 'admin_post_pcc_export_whitelist', array( $this, 'handle_export_whitelist' ) );
		add_action( 'admin_post_pcc_import_whitelist', array( $this, 'handle_import_whitelist' ) );
		add_action( 'admin_post_pcc_save_schedule', array( $this, 'handle_save_schedule' ) );
		add_action( 'admin_post_pcc_save_options', array( $this, 'handle_save_options' ) );
		add_action( 'admin_post_pcc_clear_runtime_log', array( $this, 'handle_clear_runtime_log' ) );
		add_action( 'admin_post_pcc_scan_plugin', array( $this, 'handle_scan_plugin' ) );
		add_action( 'admin_notices', array( $this, 'auto_rescan_notice' ) );

		add_action( 'wp_ajax_pcc_start_scan', array( $this, 'ajax_start_scan' ) );
		add_action( 'wp_ajax_pcc_scan_batch', array( $this, 'ajax_scan_batch' ) );
		add_action( 'wp_ajax_pcc_cancel_scan', array( $this, 'ajax_cancel_scan' ) );
		add_action( 'wp_ajax_pcc_pause_scan', array( $this, 'ajax_pause_scan' ) );
		add_action( 'wp_ajax_pcc_resume_scan', array( $this, 'ajax_resume_scan' ) );
		add_action( 'wp_ajax_pcc_mark_false_positive', array( $this, 'ajax_mark_false_positive' ) );
		add_action( 'wp_ajax_pcc_compare_scans', array( $this, 'ajax_compare_scans' ) );
		add_action( 'wp_ajax_pcc_save_intro_collapsed', array( $this, 'ajax_save_intro_collapsed' ) );

		add_filter( 'manage_plugins_columns', array( $this, 'add_plugin_column' ) );
		add_action( 'manage_plugins_custom_column', array( $this, 'render_plugin_column' ), 10, 3 );

		add_filter( 'manage_themes_columns', array( $this, 'add_theme_column' ) );
		add_action( 'manage_themes_custom_column', array( $this, 'render_theme_column' ), 10, 3 );

		add_filter( 'plugin_action_links_' . plugin_basename( PCC_FILE ), array( $this, 'plugin_action_links' ) );
	}

	public function has_volade_sdk() {
		return class_exists( 'Volade_SDK' ) && Volade_SDK::get_instance();
	}

	public function uses_volade_menu() {
		return $this->has_volade_sdk();
	}

	public function plugin_action_links( $links ) {
		$url = admin_url( $this->settings_url( false ) );
		array_unshift(
			$links,
			'<a href="' . esc_url( $url ) . '">' . esc_html__( 'Scan', 'php-compatibility-checker-by-volade' ) . '</a>'
		);
		return $links;
	}

	public function register_volade_menu() {
		$sdk = $this->uses_volade_menu() ? Volade_SDK::get_instance() : null;
		if ( ! $sdk ) {
			return;
		}

		$sdk->register_plugin_submenu(
			PCC_SLUG,
			__( 'PHP Compatibility Checker by Volade', 'php-compatibility-checker-by-volade' ),
			__( 'PHP Compatibility', 'php-compatibility-checker-by-volade' ),
			array( $this, 'render_page' )
		);
	}

	public function register_menu() {
		if ( $this->uses_volade_menu() ) {
			return;
		}

		add_management_page(
			__( 'PHP Compatibility Checker by Volade', 'php-compatibility-checker-by-volade' ),
			__( 'PHP Compatibility', 'php-compatibility-checker-by-volade' ),
			'manage_options',
			self::FALLBACK_SLUG,
			array( $this, 'render_page' )
		);
	}

	public function page_slug() {
		return $this->uses_volade_menu() ? Volade_SDK::get_plugin_page_slug( PCC_SLUG ) : self::FALLBACK_SLUG;
	}

	public static function instance_settings_path( PCC_Plugin $plugin = null ) {
		$admin = $plugin ? $plugin->admin : null;
		if ( $admin && $admin->uses_volade_menu() ) {
			return $admin->settings_url( false );
		}
		return 'tools.php?page=' . self::FALLBACK_SLUG;
	}

	private function settings_url( $with_updated = true, $extra = array() ) {
		unset( $with_updated );
		if ( $this->uses_volade_menu() ) {
			$args = array_merge( array( 'page' => $this->page_slug() ), $extra );
			return 'admin.php?' . http_build_query( $args );
		}
		$args = array_merge( array( 'page' => self::FALLBACK_SLUG ), $extra );
		return 'tools.php?' . http_build_query( $args );
	}

	public function enqueue_assets( $hook ) {
		$allowed = array(
			'volade_page_' . $this->page_slug(),
			'toplevel_page_volade',
			'tools_page_' . self::FALLBACK_SLUG,
		);

		if ( ! in_array( $hook, $allowed, true ) && 'plugins.php' !== $hook && 'themes.php' !== $hook && 'index.php' !== $hook ) {
			return;
		}

		if ( $this->has_volade_sdk() && PCC_Plugin::instance()->volade ) {
			$sdk = PCC_Plugin::instance()->volade;
			wp_enqueue_style( 'volade-sdk-admin', $sdk->get_url() . 'assets/admin.css', array(), '1.3.2' );
		}

		$deps = ( $this->has_volade_sdk() && PCC_Plugin::instance()->volade ) ? array( 'volade-sdk-admin' ) : array();
		wp_enqueue_style( 'pcc-admin', PCC_URL . 'assets/css/admin.css', $deps, PCC_VERSION );
		wp_enqueue_script( 'pcc-admin', PCC_URL . 'assets/js/admin.js', array(), PCC_VERSION, true );
		wp_localize_script(
			'pcc-admin',
			'pccAdmin',
			array(
				'ajaxUrl'    => admin_url( 'admin-ajax.php' ),
				'nonce'      => wp_create_nonce( 'pcc_ui' ),
				'scanState'  => $this->plugin->settings->get_scan_state(),
				'i18n'       => array(
					'scanning'     => __( 'Scanning…', 'php-compatibility-checker-by-volade' ),
					'complete'     => __( 'Scan complete', 'php-compatibility-checker-by-volade' ),
					'error'        => __( 'Scan failed. Try again.', 'php-compatibility-checker-by-volade' ),
					'cancelled'    => __( 'Scan cancelled.', 'php-compatibility-checker-by-volade' ),
					'confirmStop'  => __( 'Stop the current scan?', 'php-compatibility-checker-by-volade' ),
					'paused'       => __( 'Scan paused', 'php-compatibility-checker-by-volade' ),
					'resuming'     => __( 'Resuming scan…', 'php-compatibility-checker-by-volade' ),
					'copied'       => __( 'Copied', 'php-compatibility-checker-by-volade' ),
					'filterEmpty'  => __( 'No findings match your filter.', 'php-compatibility-checker-by-volade' ),
				),
				'errorHints' => PCC_Static_Analyzer::error_hints(),
			)
		);
	}

	public static function is_intro_collapsed( $user_id = 0 ) {
		$user_id = $user_id ? (int) $user_id : get_current_user_id();
		if ( ! $user_id ) {
			return false;
		}
		return '1' === get_user_meta( $user_id, self::USER_META_INTRO_COLLAPSED, true );
	}

	public function ajax_save_intro_collapsed() {
		check_ajax_referer( 'pcc_ui', 'nonce' );
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Access denied.', 'php-compatibility-checker-by-volade' ) ), 403 );
		}
		$collapsed = ! empty( $_POST['collapsed'] ) && '1' === sanitize_key( wp_unslash( $_POST['collapsed'] ) );
		update_user_meta( get_current_user_id(), self::USER_META_INTRO_COLLAPSED, $collapsed ? '1' : '0' );
		wp_send_json_success( array( 'collapsed' => $collapsed ) );
	}

	public function ajax_start_scan() {
		check_ajax_referer( 'pcc_ui', 'nonce' );
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Access denied.', 'php-compatibility-checker-by-volade' ) ), 403 );
		}

		$config = array_merge(
			$this->plugin->settings->all(),
			array(
				'target_php'           => sanitize_text_field( wp_unslash( $_POST['target_php'] ?? '' ) ),
				'target_wp'            => sanitize_text_field( wp_unslash( $_POST['target_wp'] ?? '' ) ),
				'baseline_php'         => sanitize_text_field( wp_unslash( $_POST['baseline_php'] ?? '' ) ),
				'delta_mode'           => ! empty( $_POST['delta_mode'] ),
				'scan_plugins'         => ! empty( $_POST['scan_plugins'] ),
				'scan_themes'          => ! empty( $_POST['scan_themes'] ),
				'scan_mu_plugins'      => ! empty( $_POST['scan_mu_plugins'] ),
				'scan_dropins'         => ! empty( $_POST['scan_dropins'] ),
				'scan_active_first'    => ! empty( $_POST['scan_active_first'] ),
				'scan_parent'          => ! empty( $_POST['scan_parent'] ),
				'skip_vendor'          => ! isset( $_POST['skip_vendor'] ) || ! empty( $_POST['skip_vendor'] ),
				'batch_size'           => absint( wp_unslash( $_POST['batch_size'] ?? 0 ) ),
				'selected_plugins'     => isset( $_POST['selected_plugins'] ) ? array_map( 'sanitize_key', (array) wp_unslash( $_POST['selected_plugins'] ) ) : array(),
				'selected_themes'      => isset( $_POST['selected_themes'] ) ? array_map( 'sanitize_key', (array) wp_unslash( $_POST['selected_themes'] ) ) : array(),
			)
		);

		$result = $this->plugin->scanner->start_scan( $config );
		if ( is_wp_error( $result ) ) {
			wp_send_json_error( array( 'message' => $result->get_error_message() ) );
		}

		wp_send_json_success( array( 'started' => true ) );
	}

	public function ajax_scan_batch() {
		check_ajax_referer( 'pcc_ui', 'nonce' );
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Access denied.', 'php-compatibility-checker-by-volade' ) ), 403 );
		}

		$result = $this->plugin->scanner->process_batch();
		wp_send_json_success( $result );
	}

	public function ajax_cancel_scan() {
		check_ajax_referer( 'pcc_ui', 'nonce' );
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Access denied.', 'php-compatibility-checker-by-volade' ) ), 403 );
		}
		$this->plugin->scanner->cancel_scan();
		wp_send_json_success( array( 'cancelled' => true ) );
	}

	public function ajax_pause_scan() {
		check_ajax_referer( 'pcc_ui', 'nonce' );
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Access denied.', 'php-compatibility-checker-by-volade' ) ), 403 );
		}
		$ok = $this->plugin->scanner->pause_scan();
		wp_send_json_success( array( 'paused' => $ok ) );
	}

	public function ajax_resume_scan() {
		check_ajax_referer( 'pcc_ui', 'nonce' );
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Access denied.', 'php-compatibility-checker-by-volade' ) ), 403 );
		}
		$ok = $this->plugin->scanner->resume_scan();
		wp_send_json_success( array( 'resumed' => $ok ) );
	}

	public function ajax_compare_scans() {
		check_ajax_referer( 'pcc_ui', 'nonce' );
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Access denied.', 'php-compatibility-checker-by-volade' ) ), 403 );
		}
		$id_a = sanitize_text_field( wp_unslash( $_POST['scan_a'] ?? '' ) );
		$id_b = sanitize_text_field( wp_unslash( $_POST['scan_b'] ?? '' ) );
		$result = $this->plugin->settings->compare_history( $id_a, $id_b );
		if ( is_wp_error( $result ) ) {
			wp_send_json_error( array( 'message' => $result->get_error_message() ) );
		}
		wp_send_json_success( $result );
	}

	public function ajax_mark_false_positive() {
		check_ajax_referer( 'pcc_ui', 'nonce' );
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Access denied.', 'php-compatibility-checker-by-volade' ) ), 403 );
		}
		if ( ! $this->plugin->has_feature( 'false_positive_mark' ) ) {
			wp_send_json_error( array( 'message' => __( 'Volade account required.', 'php-compatibility-checker-by-volade' ) ) );
		}
		$fp = sanitize_text_field( wp_unslash( $_POST['fingerprint'] ?? '' ) );
		$this->plugin->settings->add_false_positive( $fp );
		wp_send_json_success( array( 'marked' => true ) );
	}

	public function handle_apply_preset() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'Access denied.', 'php-compatibility-checker-by-volade' ) );
		}
		check_admin_referer( 'pcc_apply_preset' );
		$slug   = sanitize_key( wp_unslash( $_POST['pcc_preset'] ?? '' ) );
		$result = $this->plugin->settings->apply_preset( $slug );
		$arg    = is_wp_error( $result ) ? 'preset_error' : 'preset_applied';
		wp_safe_redirect( add_query_arg( array( $arg => '1', 'preset' => $slug ), admin_url( $this->settings_url( false ) ) ) );
		exit;
	}

	public function handle_export_report() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'Access denied.', 'php-compatibility-checker-by-volade' ) );
		}
		check_admin_referer( 'pcc_export_report' );
		$json = $this->plugin->settings->export_scan_json();
		$name = 'pcc-report-' . gmdate( 'Y-m-d' ) . '.json';
		nocache_headers();
		header( 'Content-Type: application/json; charset=utf-8' );
		header( 'Content-Disposition: attachment; filename="' . $name . '"' );
		echo $json; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		exit;
	}

	public function handle_export_csv() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'Access denied.', 'php-compatibility-checker-by-volade' ) );
		}
		check_admin_referer( 'pcc_export_csv' );
		if ( ! $this->plugin->has_feature( 'export_csv' ) ) {
			wp_die( esc_html__( 'CSV export requires V+ Premium.', 'php-compatibility-checker-by-volade' ) );
		}
		$csv  = $this->plugin->settings->export_scan_csv();
		$name = 'pcc-report-' . gmdate( 'Y-m-d' ) . '.csv';
		nocache_headers();
		header( 'Content-Type: text/csv; charset=utf-8' );
		header( 'Content-Disposition: attachment; filename="' . $name . '"' );
		echo $csv; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		exit;
	}

	public function handle_export_whitelist() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'Access denied.', 'php-compatibility-checker-by-volade' ) );
		}
		check_admin_referer( 'pcc_export_whitelist' );
		if ( ! $this->plugin->has_feature( 'false_positive_mark' ) ) {
			wp_die( esc_html__( 'Volade account required.', 'php-compatibility-checker-by-volade' ) );
		}
		$json = $this->plugin->settings->export_false_positives_json();
		$name = 'pcc-whitelist-' . gmdate( 'Y-m-d' ) . '.json';
		nocache_headers();
		header( 'Content-Type: application/json; charset=utf-8' );
		header( 'Content-Disposition: attachment; filename="' . $name . '"' );
		echo $json; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		exit;
	}

	public function handle_import_whitelist() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'Access denied.', 'php-compatibility-checker-by-volade' ) );
		}
		check_admin_referer( 'pcc_import_whitelist' );
		$upload_tmp = isset( $_FILES['pcc_whitelist_file']['tmp_name'] )
			? sanitize_text_field( wp_unslash( $_FILES['pcc_whitelist_file']['tmp_name'] ) )
			: '';
		if ( '' === $upload_tmp || ! is_uploaded_file( $upload_tmp ) ) {
			wp_safe_redirect( add_query_arg( 'whitelist_error', '1', admin_url( $this->settings_url( false ) ) ) );
			exit;
		}
		$json   = file_get_contents( $upload_tmp ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
		$result = $this->plugin->settings->import_false_positives_json( $json );
		$arg    = is_wp_error( $result ) ? 'whitelist_error' : 'whitelist_imported';
		wp_safe_redirect( add_query_arg( $arg, '1', admin_url( $this->settings_url( false ) ) ) );
		exit;
	}

	public function handle_save_schedule() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'Access denied.', 'php-compatibility-checker-by-volade' ) );
		}
		check_admin_referer( 'pcc_save_schedule' );
		if ( ! $this->plugin->has_feature( 'scheduled_scan' ) ) {
			wp_die( esc_html__( 'Scheduled scans require V+ Premium.', 'php-compatibility-checker-by-volade' ) );
		}
		$this->plugin->scheduler->save_settings(
			array(
				'enabled'   => ! empty( $_POST['schedule_enabled'] ),
				'frequency' => sanitize_key( wp_unslash( $_POST['schedule_frequency'] ?? 'weekly' ) ),
				'email'     => sanitize_email( wp_unslash( $_POST['schedule_email'] ?? '' ) ),
			)
		);
		wp_safe_redirect( add_query_arg( 'schedule_saved', '1', admin_url( $this->settings_url( false ) ) ) );
		exit;
	}

	public function handle_save_options() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'Access denied.', 'php-compatibility-checker-by-volade' ) );
		}
		check_admin_referer( 'pcc_save_options' );

		$this->plugin->settings->save(
			array_merge(
				$this->plugin->settings->all(),
				array(
					'default_delta_mode'   => ! empty( $_POST['default_delta_mode'] ),
					'errors_only'          => ! empty( $_POST['errors_only'] ),
					'runtime_monitor'      => ! empty( $_POST['runtime_monitor'] ),
					'auto_rescan_update'   => ! empty( $_POST['auto_rescan_update'] ),
					'scan_active_first'    => ! empty( $_POST['scan_active_first'] ),
					'max_warnings_verdict' => absint( wp_unslash( $_POST['max_warnings_verdict'] ?? 0 ) ),
					'batch_size'           => absint( wp_unslash( $_POST['batch_size'] ?? 0 ) ),
					'custom_excludes'      => isset( $_POST['custom_excludes'] )
						? sanitize_textarea_field( wp_unslash( $_POST['custom_excludes'] ) )
						: '',
				)
			)
		);

		wp_safe_redirect( add_query_arg( 'options_saved', '1', admin_url( $this->settings_url( false ) ) ) );
		exit;
	}

	public function handle_clear_runtime_log() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'Access denied.', 'php-compatibility-checker-by-volade' ) );
		}
		check_admin_referer( 'pcc_clear_runtime_log' );
		$this->plugin->runtime->clear_log();
		wp_safe_redirect( add_query_arg( 'runtime_cleared', '1', admin_url( $this->settings_url( false ) ) ) );
		exit;
	}

	public function handle_scan_plugin() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'Access denied.', 'php-compatibility-checker-by-volade' ) );
		}
		check_admin_referer( 'pcc_scan_plugin' );
		$slug = sanitize_key( wp_unslash( $_GET['plugin'] ?? '' ) );
		if ( ! $slug ) {
			wp_safe_redirect( admin_url( 'plugins.php' ) );
			exit;
		}

		$result = $this->plugin->scanner->start_single_plugin_scan( $slug );
		if ( is_wp_error( $result ) ) {
			wp_safe_redirect(
				add_query_arg(
					array(
						'pcc_scan_error' => rawurlencode( $result->get_error_message() ),
					),
					admin_url( $this->settings_url( false ) )
				)
			);
			exit;
		}

		$guard = 0;
		do {
			$batch = $this->plugin->scanner->process_batch();
			$guard++;
		} while ( empty( $batch['done'] ) && $guard < 5000 );

		wp_safe_redirect( add_query_arg( 'pcc_scan_done', $slug, admin_url( $this->settings_url( false ) ) ) );
		exit;
	}

	public function auto_rescan_notice() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		$data = get_transient( 'pcc_auto_rescan_notice' );
		if ( ! is_array( $data ) || empty( $data['slug'] ) ) {
			return;
		}
		delete_transient( 'pcc_auto_rescan_notice' );
		$verdict = $this->plugin->scanner->verdict_label( $data['verdict'] ?? 'unknown' );
		echo '<div class="notice notice-info is-dismissible"><p>';
		printf(
			/* translators: 1: plugin slug, 2: verdict label */
			esc_html__( 'Auto-rescan after update: %1$s — %2$s', 'php-compatibility-checker-by-volade' ),
			esc_html( $data['slug'] ),
			esc_html( $verdict )
		);
		echo '</p></div>';
	}

	public function add_plugin_column( $columns ) {
		$columns['pcc_compat'] = __( 'PHP', 'php-compatibility-checker-by-volade' );
		return $columns;
	}

	public function render_plugin_column( $column, $plugin_file, $data ) {
		unset( $data );
		if ( 'pcc_compat' !== $column ) {
			return;
		}
		$status = $this->plugin->settings->get_plugin_badge_status( $plugin_file );
		$labels = array(
			'ready'   => __( 'Ready', 'php-compatibility-checker-by-volade' ),
			'warning' => __( 'Warnings', 'php-compatibility-checker-by-volade' ),
			'error'   => __( 'Errors', 'php-compatibility-checker-by-volade' ),
			'unknown' => '—',
		);
		echo '<span class="pcc-badge pcc-badge-' . esc_attr( $status ) . '">' . esc_html( $labels[ $status ] ?? '—' ) . '</span> ';

		if ( $this->plugin->has_feature( 'scan_all_plugins' ) ) {
			$slug = dirname( $plugin_file );
			if ( '.' === $slug ) {
				$slug = basename( $plugin_file, '.php' );
			}
			$url = wp_nonce_url(
				admin_url( 'admin-post.php?action=pcc_scan_plugin&plugin=' . rawurlencode( $slug ) ),
				'pcc_scan_plugin'
			);
			echo '<a href="' . esc_url( $url ) . '" class="pcc-scan-link">' . esc_html__( 'Scan', 'php-compatibility-checker-by-volade' ) . '</a>';
		}
	}

	public function add_theme_column( $columns ) {
		$columns['pcc_compat'] = __( 'PHP', 'php-compatibility-checker-by-volade' );
		return $columns;
	}

	public function render_theme_column( $column, $stylesheet, $theme ) {
		unset( $theme );
		if ( 'pcc_compat' !== $column ) {
			return;
		}
		$status = $this->plugin->settings->get_theme_badge_status( $stylesheet );
		$labels = array(
			'ready'   => __( 'Ready', 'php-compatibility-checker-by-volade' ),
			'warning' => __( 'Warnings', 'php-compatibility-checker-by-volade' ),
			'error'   => __( 'Errors', 'php-compatibility-checker-by-volade' ),
			'unknown' => '—',
		);
		echo '<span class="pcc-badge pcc-badge-' . esc_attr( $status ) . '">' . esc_html( $labels[ $status ] ?? '—' ) . '</span>';
	}

	public function render_page() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		$settings        = $this->plugin->settings->all();
		$access          = $this->plugin->volade ? $this->plugin->volade->get_access_level() : 'guest';
		$access_label    = $this->plugin->volade ? $this->plugin->volade->get_access_level_label( $access ) : __( 'No account', 'php-compatibility-checker-by-volade' );
		$presets         = PCC_Presets::all();
		$targets         = $this->plugin->scanner->allowed_target_versions();
		$scan_targets    = $this->plugin->scanner->get_scan_targets();
		$last_scan       = $this->plugin->settings->get_last_scan();
		$scan_state      = $this->plugin->settings->get_scan_state();
		$history         = $this->plugin->settings->get_scan_history();
		$all_plugins     = function_exists( 'get_plugins' ) ? get_plugins() : array();
		$all_themes      = wp_get_themes();
		$runtime_php     = phpversion();
		$env_check       = PCC_Environment::check();
		$conflicts       = PCC_Audit::detect_conflicts();
		$schedule        = $this->plugin->scheduler->get_settings();
		$can_guest_scan  = $this->plugin->scanner->can_guest_scan();
		$active_plugins  = (array) get_option( 'active_plugins', array() );
		$runtime_log     = $this->plugin->runtime->get_log();
		$wp_targets      = PCC_Wp_Deprecations::available_targets();
		$batch_recommended = PCC_Environment::recommended_batch_size();

		$wrap_class = $this->uses_volade_menu() ? 'volade-wrap pcc-wrap' : 'pcc-wrap pcc-wrap-standalone';
		echo '<div class="' . esc_attr( $wrap_class ) . '">';
		include PCC_DIR . 'admin/views/scan-page.php';
		echo '</div>';
	}
}
