<?php
/**
 * Admin menu registration.
 *
 * @package GoValid_QR
 */

defined( 'ABSPATH' ) || exit;

class GoValid_Admin {

	/**
	 * Register admin hooks.
	 */
	public function register(): void {
		add_action( 'admin_menu', array( $this, 'add_menu_pages' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
		add_filter( 'plugin_action_links_' . GOVALID_QR_PLUGIN_BASENAME, array( $this, 'add_settings_link' ) );
	}

	/**
	 * Add admin menu pages.
	 */
	public function add_menu_pages(): void {
		add_menu_page(
			__( 'GoValid QR', 'govalid-qr-validator' ),
			__( 'GoValid QR', 'govalid-qr-validator' ),
			'edit_posts',
			'govalid-qr-generator',
			array( $this, 'render_generator_page' ),
			GOVALID_QR_PLUGIN_URL . 'assets/images/govalid-icon.svg?v2=' . GOVALID_QR_VERSION,
			80
		);

		// 1. QR Generator (top item — matches parent slug).
		add_submenu_page(
			'govalid-qr-generator',
			__( 'QR Generator', 'govalid-qr-validator' ),
			__( 'QR Generator', 'govalid-qr-validator' ),
			'edit_posts',
			'govalid-qr-generator',
			array( $this, 'render_generator_page' )
		);

		// 2. Humanize Links.
		add_submenu_page(
			'govalid-qr-generator',
			__( 'Humanize Links', 'govalid-qr-validator' ),
			__( 'Humanize Links', 'govalid-qr-validator' ),
			'edit_posts',
			'govalid-qr-links',
			array( $this, 'render_links_page' )
		);

		// 3. Forms.
		add_submenu_page(
			'govalid-qr-generator',
			__( 'Forms', 'govalid-qr-validator' ),
			__( 'Forms', 'govalid-qr-validator' ),
			'edit_posts',
			'govalid-qr-forms',
			array( $this, 'render_forms_page' )
		);

		// 4. List QR.
		add_submenu_page(
			'govalid-qr-generator',
			__( 'List QR', 'govalid-qr-validator' ),
			__( 'List QR', 'govalid-qr-validator' ),
			'edit_posts',
			'govalid-qr-list',
			array( $this, 'render_list_page' )
		);

		// 5. Analytics.
		add_submenu_page(
			'govalid-qr-generator',
			__( 'Analytics', 'govalid-qr-validator' ),
			__( 'Analytics', 'govalid-qr-validator' ),
			'edit_posts',
			'govalid-qr-analytics',
			array( $this, 'render_analytics_page' )
		);

		// 6. Settings (last).
		add_submenu_page(
			'govalid-qr-generator',
			__( 'Settings', 'govalid-qr-validator' ),
			__( 'Settings', 'govalid-qr-validator' ),
			'manage_options',
			'govalid-qr',
			array( $this, 'render_settings_page' )
		);

		// Hidden page: Form Builder.
		add_submenu_page(
			null,
			__( 'Form Builder', 'govalid-qr-validator' ),
			'',
			'edit_posts',
			'govalid-qr-form-builder',
			array( $this, 'render_form_builder_page' )
		);

		// Hidden page: Form Submissions.
		add_submenu_page(
			null,
			__( 'Form Submissions', 'govalid-qr-validator' ),
			'',
			'edit_posts',
			'govalid-qr-form-submissions',
			array( $this, 'render_form_submissions_page' )
		);

		// Hidden page for OAuth callback.
		add_submenu_page(
			null,
			__( 'OAuth Callback', 'govalid-qr-validator' ),
			'',
			'manage_options',
			'govalid-qr-oauth-callback',
			array( $this, 'render_oauth_callback' )
		);
	}

	/**
	 * Render settings page.
	 *
	 * Flash-message GET parameters are only read after nonce verification; variables
	 * default to empty/false when the nonce is absent (normal page load without flash).
	 */
	public function render_settings_page(): void {
		$govalid_error         = '';
		$govalid_connected     = false;
		$govalid_disconnected  = false;
		$govalid_cache_cleared = false;
		$govalid_page_created  = false;
		$govalid_active_tab    = 'general';

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Only reading the nonce itself for verification below.
		$nonce_raw = isset( $_GET['_wpnonce'] ) ? sanitize_key( wp_unslash( $_GET['_wpnonce'] ) ) : '';
		if ( $nonce_raw && wp_verify_nonce( $nonce_raw, 'govalid-admin' ) ) {
			// phpcs:disable WordPress.Security.NonceVerification.Recommended
			$govalid_error         = isset( $_GET['error'] ) ? sanitize_text_field( wp_unslash( $_GET['error'] ) ) : '';
			$govalid_connected     = isset( $_GET['connected'] );
			$govalid_disconnected  = isset( $_GET['disconnected'] );
			$govalid_cache_cleared = isset( $_GET['cache_cleared'] );
			$govalid_page_created  = isset( $_GET['page_created'] );
			$govalid_active_tab    = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'general';
			// phpcs:enable WordPress.Security.NonceVerification.Recommended
		}

		include GOVALID_QR_PLUGIN_DIR . 'admin/partials/settings-page.php';
	}

	/**
	 * Render generator page.
	 */
	public function render_generator_page(): void {
		$govalid_error        = '';
		$govalid_active_tab   = 'certificate';
		$govalid_prefill_url  = '';
		$govalid_prefill_name = '';

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$nonce_raw = isset( $_GET['_wpnonce'] ) ? sanitize_key( wp_unslash( $_GET['_wpnonce'] ) ) : '';
		if ( $nonce_raw && wp_verify_nonce( $nonce_raw, 'govalid-admin' ) ) {
			// phpcs:disable WordPress.Security.NonceVerification.Recommended
			$govalid_error        = isset( $_GET['error'] ) ? sanitize_text_field( wp_unslash( $_GET['error'] ) ) : '';
			$govalid_active_tab   = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'certificate';
			$govalid_prefill_url  = isset( $_GET['prefill_url'] ) ? sanitize_url( wp_unslash( $_GET['prefill_url'] ) ) : '';
			$govalid_prefill_name = isset( $_GET['prefill_name'] ) ? sanitize_text_field( wp_unslash( $_GET['prefill_name'] ) ) : '';
			// phpcs:enable WordPress.Security.NonceVerification.Recommended
		}

		include GOVALID_QR_PLUGIN_DIR . 'admin/partials/generator-page.php';
	}

	/**
	 * Render List QR page.
	 */
	public function render_list_page(): void {
		$govalid_created      = '';
		$govalid_bulk_created = 0;
		$govalid_bulk_errors  = '';

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$nonce_raw = isset( $_GET['_wpnonce'] ) ? sanitize_key( wp_unslash( $_GET['_wpnonce'] ) ) : '';
		if ( $nonce_raw && wp_verify_nonce( $nonce_raw, 'govalid-admin' ) ) {
			// phpcs:disable WordPress.Security.NonceVerification.Recommended
			$govalid_created      = isset( $_GET['created'] ) ? sanitize_text_field( wp_unslash( $_GET['created'] ) ) : '';
			$govalid_bulk_created = isset( $_GET['bulk_created'] ) ? absint( $_GET['bulk_created'] ) : 0;
			$govalid_bulk_errors  = isset( $_GET['bulk_errors'] ) ? sanitize_text_field( wp_unslash( $_GET['bulk_errors'] ) ) : '';
			// phpcs:enable WordPress.Security.NonceVerification.Recommended
		}

		include GOVALID_QR_PLUGIN_DIR . 'admin/partials/list-page.php';
	}

	/**
	 * Render Analytics page.
	 */
	public function render_analytics_page(): void {
		include GOVALID_QR_PLUGIN_DIR . 'admin/partials/analytics-page.php';
	}

	/**
	 * Render Humanize Links page.
	 */
	public function render_links_page(): void {
		include GOVALID_QR_PLUGIN_DIR . 'admin/partials/links-page.php';
	}

	/**
	 * Render Forms list page.
	 */
	public function render_forms_page(): void {
		$govalid_deleted = false;

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$nonce_raw = isset( $_GET['_wpnonce'] ) ? sanitize_key( wp_unslash( $_GET['_wpnonce'] ) ) : '';
		if ( $nonce_raw && wp_verify_nonce( $nonce_raw, 'govalid-admin' ) ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$govalid_deleted = isset( $_GET['deleted'] ) ? 1 : 0;
		}

		// Ensure tables exist (handles upgrades without re-activation).
		GoValid_QR_Activator::maybe_create_tables();
		include GOVALID_QR_PLUGIN_DIR . 'admin/partials/forms-page.php';
	}

	/**
	 * Render Form Builder page.
	 */
	public function render_form_builder_page(): void {
		$govalid_form_id = 0;
		$govalid_saved   = 0;

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$nonce_raw = isset( $_GET['_wpnonce'] ) ? sanitize_key( wp_unslash( $_GET['_wpnonce'] ) ) : '';
		if ( $nonce_raw && wp_verify_nonce( $nonce_raw, 'govalid-admin' ) ) {
			// phpcs:disable WordPress.Security.NonceVerification.Recommended
			$govalid_form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : 0;
			$govalid_saved   = isset( $_GET['saved'] ) ? 1 : 0;
			// phpcs:enable WordPress.Security.NonceVerification.Recommended
		}

		include GOVALID_QR_PLUGIN_DIR . 'admin/partials/form-builder-page.php';
	}

	/**
	 * Render Form Submissions page.
	 */
	public function render_form_submissions_page(): void {
		$govalid_form_id = 0;

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$nonce_raw = isset( $_GET['_wpnonce'] ) ? sanitize_key( wp_unslash( $_GET['_wpnonce'] ) ) : '';
		if ( $nonce_raw && wp_verify_nonce( $nonce_raw, 'govalid-admin' ) ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$govalid_form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : 0;
		}

		include GOVALID_QR_PLUGIN_DIR . 'admin/partials/form-submissions-page.php';
	}

	/**
	 * Handle OAuth callback rendering.
	 */
	public function render_oauth_callback(): void {
		$settings = new GoValid_Admin_Settings();
		$settings->handle_oauth_callback();
	}

	/**
	 * Enqueue admin assets.
	 *
	 * @param string $hook Current admin page hook.
	 */
	public function enqueue_assets( string $hook ): void {
		// Only load on our plugin pages.
		if ( strpos( $hook, 'govalid-qr' ) === false ) {
			return;
		}

		wp_enqueue_style(
			'govalid-admin',
			GOVALID_QR_PLUGIN_URL . 'admin/css/govalid-admin.css',
			array(),
			GOVALID_QR_VERSION
		);

		wp_enqueue_script(
			'govalid-admin',
			GOVALID_QR_PLUGIN_URL . 'admin/js/govalid-admin.js',
			array( 'jquery' ),
			GOVALID_QR_VERSION,
			true
		);

		wp_localize_script( 'govalid-admin', 'govalidQR', array(
			'ajaxUrl'      => admin_url( 'admin-ajax.php' ),
			'restUrl'      => rest_url( 'govalid-qr/v1/' ),
			'baseUrl'      => GoValid_QR::get_base_url(),
			'nonce'        => wp_create_nonce( 'wp_rest' ),
			'adminNonce'   => wp_create_nonce( 'govalid-admin' ),
			'isConnected'  => GoValid_QR::is_connected(),
			'settingsUrl'  => admin_url( 'admin.php?page=govalid-qr' ),
			'pluginUrl'    => GOVALID_QR_PLUGIN_URL,
			'promoAds'     => $this->get_promo_ads(),
			'i18n'    => array(
				'confirm_disconnect'  => __( 'Are you sure you want to disconnect from GoValid?', 'govalid-qr-validator' ),
				'generating'          => __( 'Generating QR code...', 'govalid-qr-validator' ),
				'error'               => __( 'An error occurred. Please try again.', 'govalid-qr-validator' ),
				'copied'              => __( 'Copied to clipboard!', 'govalid-qr-validator' ),
				'smart_qr_desc'       => __( 'Compact QR code with 96-bit security. Perfect for tiny labels and product tags. Smallest QR code size.', 'govalid-qr-validator' ),
				'secure_qr_desc'      => __( '256-bit encryption protects your data from unauthorized changes and tampering. Balanced QR code size.', 'govalid-qr-validator' ),
				'enterprise_qr_desc'  => __( '256-bit encryption with digital signatures and non-repudiation guarantee. Tamper-proof verification with legally binding proof of origin. Large QR code size.', 'govalid-qr-validator' ),
				'suggesting'          => __( 'Generating suggestions...', 'govalid-qr-validator' ),
				'creating_link'       => __( 'Creating link...', 'govalid-qr-validator' ),
				'checking_slug'       => __( 'Checking...', 'govalid-qr-validator' ),
				'slug_available'      => __( 'Available!', 'govalid-qr-validator' ),
				'slug_taken'          => __( 'Already taken.', 'govalid-qr-validator' ),
				'slug_reserved'       => __( 'Reserved.', 'govalid-qr-validator' ),
				'confirm_delete_link' => __( 'Are you sure you want to delete this link?', 'govalid-qr-validator' ),
				'link_deleted'        => __( 'Link deleted.', 'govalid-qr-validator' ),
				'link_created'        => __( 'Link created!', 'govalid-qr-validator' ),
				'no_links'            => __( 'No humanize links yet. Create one above!', 'govalid-qr-validator' ),
				'loading_links'       => __( 'Loading links...', 'govalid-qr-validator' ),
				'active'              => __( 'Active', 'govalid-qr-validator' ),
				'inactive'            => __( 'Inactive', 'govalid-qr-validator' ),
				'select_suggestion'   => __( 'Select a suggestion below, edit the slug if needed, then create.', 'govalid-qr-validator' ),
				'pin_enter_6'         => __( 'Please enter all 6 digits.', 'govalid-qr-validator' ),
				'pin_invalid'         => __( 'Invalid PIN.', 'govalid-qr-validator' ),
				'pin_required'        => __( 'Please verify your signing PIN first.', 'govalid-qr-validator' ),
				'verify_pin'          => __( 'Verify PIN', 'govalid-qr-validator' ),
				'verifying'           => __( 'Verifying...', 'govalid-qr-validator' ),
				'loading_qr'          => __( 'Loading QR codes...', 'govalid-qr-validator' ),
				'no_qr'               => __( 'No QR codes generated from WordPress yet.', 'govalid-qr-validator' ),
				'copy'                => __( 'Copy', 'govalid-qr-validator' ),
				'verify'              => __( 'Verify', 'govalid-qr-validator' ),
				'scans_label'         => __( 'scans', 'govalid-qr-validator' ),
				'view_detail'         => __( 'View', 'govalid-qr-validator' ),
				'delete'              => __( 'Delete', 'govalid-qr-validator' ),
				'confirm_delete_qr'   => __( 'Are you sure you want to delete this QR code?', 'govalid-qr-validator' ),
				'qr_deleted'          => __( 'QR code deleted.', 'govalid-qr-validator' ),
				'confirm_bulk_delete_qr' => __( 'Delete {count} selected QR code(s)?', 'govalid-qr-validator' ),
				'bulk_deleted'        => __( 'Selected QR codes deleted.', 'govalid-qr-validator' ),
				'delete_selected'     => __( 'Delete Selected', 'govalid-qr-validator' ),
				'deleting'            => __( 'Deleting...', 'govalid-qr-validator' ),
				'download'            => __( 'Download', 'govalid-qr-validator' ),
				'export_excel'        => __( 'Export Excel', 'govalid-qr-validator' ),
				'exporting'           => __( 'Exporting...', 'govalid-qr-validator' ),
			),
			'i18nLabel' => array(
				'label_layout'       => __( 'Label Layout', 'govalid-qr-validator' ),
				'export_pdf'         => __( 'PDF', 'govalid-qr-validator' ),
				'export_png'         => __( 'PNG', 'govalid-qr-validator' ),
				'export_jpg'         => __( 'JPG', 'govalid-qr-validator' ),
				'print'              => __( 'Print', 'govalid-qr-validator' ),
				'close'              => __( 'Close', 'govalid-qr-validator' ),
				'selected_qr_codes'  => __( 'Selected QR Codes', 'govalid-qr-validator' ),
				'add_more'           => __( 'Add More', 'govalid-qr-validator' ),
				'paper_settings'     => __( 'Paper Settings', 'govalid-qr-validator' ),
				'label_settings'     => __( 'Label Settings', 'govalid-qr-validator' ),
				'frame_settings'     => __( 'Frame Settings', 'govalid-qr-validator' ),
				'paper_size'         => __( 'Paper Size', 'govalid-qr-validator' ),
				'orientation'        => __( 'Orientation', 'govalid-qr-validator' ),
				'portrait'           => __( 'Portrait', 'govalid-qr-validator' ),
				'landscape'          => __( 'Landscape', 'govalid-qr-validator' ),
				'columns'            => __( 'Columns', 'govalid-qr-validator' ),
				'rows'               => __( 'Rows', 'govalid-qr-validator' ),
				'margins'            => __( 'Margins (mm)', 'govalid-qr-validator' ),
				'spacing'            => __( 'Spacing (mm)', 'govalid-qr-validator' ),
				'qr_size'            => __( 'QR Size (mm)', 'govalid-qr-validator' ),
				'qr_position'        => __( 'QR Position', 'govalid-qr-validator' ),
				'show_label'         => __( 'Show Label', 'govalid-qr-validator' ),
				'label_content'      => __( 'Label Content', 'govalid-qr-validator' ),
				'name'               => __( 'Name', 'govalid-qr-validator' ),
				'id'                 => __( 'ID', 'govalid-qr-validator' ),
				'both'               => __( 'Both', 'govalid-qr-validator' ),
				'position'           => __( 'Position', 'govalid-qr-validator' ),
				'font'               => __( 'Font', 'govalid-qr-validator' ),
				'size'               => __( 'Size', 'govalid-qr-validator' ),
				'color'              => __( 'Color', 'govalid-qr-validator' ),
				'background'         => __( 'Background', 'govalid-qr-validator' ),
				'frame_style'        => __( 'Frame Style', 'govalid-qr-validator' ),
				'frame_color'        => __( 'Frame Color', 'govalid-qr-validator' ),
				'fill_color'         => __( 'Fill Color', 'govalid-qr-validator' ),
				'stroke_width'       => __( 'Stroke Width', 'govalid-qr-validator' ),
				'none'               => __( 'None', 'govalid-qr-validator' ),
				'basic'              => __( 'Basic', 'govalid-qr-validator' ),
				'rounded'            => __( 'Rounded', 'govalid-qr-validator' ),
				'double'             => __( 'Double', 'govalid-qr-validator' ),
				'dashed'             => __( 'Dashed', 'govalid-qr-validator' ),
				'dotted'             => __( 'Dotted', 'govalid-qr-validator' ),
				'shadow'             => __( 'Shadow', 'govalid-qr-validator' ),
				'zoom_in'            => __( 'Zoom In', 'govalid-qr-validator' ),
				'zoom_out'           => __( 'Zoom Out', 'govalid-qr-validator' ),
				'reset_zoom'         => __( 'Reset Zoom', 'govalid-qr-validator' ),
				'page_of'            => __( 'Page {current} of {total}', 'govalid-qr-validator' ),
				'exporting'          => __( 'Exporting...', 'govalid-qr-validator' ),
				'preparing_print'    => __( 'Preparing print...', 'govalid-qr-validator' ),
				'add_qr_codes'       => __( 'Add QR Codes', 'govalid-qr-validator' ),
				'search_qr'          => __( 'Search QR codes...', 'govalid-qr-validator' ),
				'add_selected'       => __( 'Add Selected', 'govalid-qr-validator' ),
				'cancel'             => __( 'Cancel', 'govalid-qr-validator' ),
				'no_qr_available'    => __( 'No QR codes available.', 'govalid-qr-validator' ),
				'top'                => __( 'Top', 'govalid-qr-validator' ),
				'bottom'             => __( 'Bottom', 'govalid-qr-validator' ),
				'left'               => __( 'Left', 'govalid-qr-validator' ),
				'right'              => __( 'Right', 'govalid-qr-validator' ),
				'center'             => __( 'Center', 'govalid-qr-validator' ),
				'custom'             => __( 'Custom', 'govalid-qr-validator' ),
				'width_mm'           => __( 'Width (mm)', 'govalid-qr-validator' ),
				'height_mm'          => __( 'Height (mm)', 'govalid-qr-validator' ),
				'layout_presets'     => __( 'Layout Presets', 'govalid-qr-validator' ),
				'select_preset'      => __( '— Select Preset —', 'govalid-qr-validator' ),
				'save_current'       => __( 'Save Current', 'govalid-qr-validator' ),
				'delete_preset'      => __( 'Delete', 'govalid-qr-validator' ),
				'last_used'          => __( 'Last Used', 'govalid-qr-validator' ),
				'default_settings'   => __( 'Default Settings', 'govalid-qr-validator' ),
				'preset_name_prompt' => __( 'Enter a name for this preset:', 'govalid-qr-validator' ),
				'preset_saved'       => __( 'Preset saved!', 'govalid-qr-validator' ),
				'preset_deleted'     => __( 'Preset deleted.', 'govalid-qr-validator' ),
				'confirm_delete'     => __( 'Delete this preset?', 'govalid-qr-validator' ),
				'templates'          => __( 'Templates', 'govalid-qr-validator' ),
				'saved_presets'      => __( 'My Presets', 'govalid-qr-validator' ),
			),
		) );

		// Generator page — load Leaflet for timeline map; inject prefill data if present.
		if ( strpos( $hook, 'govalid-qr-generator' ) !== false ) {
			$prefill_url  = '';
			$prefill_name = '';
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$enqueue_nonce = isset( $_GET['_wpnonce'] ) ? sanitize_key( wp_unslash( $_GET['_wpnonce'] ) ) : '';
			if ( $enqueue_nonce && wp_verify_nonce( $enqueue_nonce, 'govalid-admin' ) ) {
				// phpcs:disable WordPress.Security.NonceVerification.Recommended
				$prefill_url  = isset( $_GET['prefill_url'] )  ? sanitize_url( wp_unslash( $_GET['prefill_url'] ) )  : '';
				$prefill_name = isset( $_GET['prefill_name'] ) ? sanitize_text_field( wp_unslash( $_GET['prefill_name'] ) ) : '';
				// phpcs:enable WordPress.Security.NonceVerification.Recommended
			}
			if ( $prefill_url || $prefill_name ) {
				wp_add_inline_script(
					'govalid-admin',
					'document.addEventListener("DOMContentLoaded", function() {' .
					'var nameField = document.getElementById("govalid-qr-name") || document.querySelector("[name=\"qr_name\"]");' .
					'var urlField  = document.getElementById("govalid-qr-url")  || document.querySelector("[name=\"qr_url\"]");' .
					'if (nameField && ' . wp_json_encode( $prefill_name ) . ') { nameField.value = ' . wp_json_encode( $prefill_name ) . '; }' .
					'if (urlField  && ' . wp_json_encode( $prefill_url )  . ') { urlField.value  = ' . wp_json_encode( $prefill_url )  . '; }' .
					'});'
				);
			}
			wp_enqueue_style(
				'leaflet-css',
				GOVALID_QR_PLUGIN_URL . 'admin/vendor/leaflet.css',
				array(),
				'1.9.4'
			);

			wp_enqueue_script(
				'leaflet-js',
				GOVALID_QR_PLUGIN_URL . 'admin/vendor/leaflet.js',
				array(),
				'1.9.4',
				true
			);
		}

		// Links page — load QR code styling for live QR designer.
		if ( strpos( $hook, 'govalid-qr-links' ) !== false ) {
			wp_enqueue_media();

			wp_enqueue_script(
				'qr-code-styling',
				GOVALID_QR_PLUGIN_URL . 'admin/vendor/qr-code-styling.min.js',
				array(),
				'1.6.0',
				true
			);
		}

		// List page — load label layout assets.
		if ( strpos( $hook, 'govalid-qr-list' ) !== false ) {
			wp_enqueue_script(
				'html2canvas',
				GOVALID_QR_PLUGIN_URL . 'admin/vendor/html2canvas.min.js',
				array(),
				'1.4.1',
				true
			);

			wp_enqueue_script(
				'jspdf',
				GOVALID_QR_PLUGIN_URL . 'admin/vendor/jspdf.umd.min.js',
				array(),
				'2.5.2',
				true
			);

			wp_enqueue_script(
				'sortablejs',
				GOVALID_QR_PLUGIN_URL . 'admin/vendor/sortable.min.js',
				array(),
				'1.15.6',
				true
			);

			wp_enqueue_script(
				'sheetjs',
				GOVALID_QR_PLUGIN_URL . 'admin/vendor/xlsx.mini.min.js',
				array(),
				'0.20.3',
				true
			);

			wp_enqueue_style(
				'govalid-label-layout',
				GOVALID_QR_PLUGIN_URL . 'admin/css/govalid-label-layout.css',
				array( 'govalid-admin' ),
				GOVALID_QR_VERSION
			);

			wp_enqueue_script(
				'govalid-label-layout',
				GOVALID_QR_PLUGIN_URL . 'admin/js/govalid-label-layout.js',
				array( 'jquery', 'html2canvas', 'jspdf', 'sortablejs', 'govalid-admin' ),
				GOVALID_QR_VERSION,
				true
			);
		}

		// Forms pages — load form builder / forms admin assets.
		if ( strpos( $hook, 'govalid-qr-form-builder' ) !== false ) {
			wp_enqueue_media();

			wp_enqueue_script(
				'sortablejs',
				GOVALID_QR_PLUGIN_URL . 'admin/vendor/sortable.min.js',
				array(),
				'1.15.6',
				true
			);

			wp_enqueue_style(
				'govalid-form-builder',
				GOVALID_QR_PLUGIN_URL . 'admin/css/govalid-form-builder.css',
				array( 'govalid-admin' ),
				GOVALID_QR_VERSION
			);

			wp_enqueue_script(
				'govalid-form-builder',
				GOVALID_QR_PLUGIN_URL . 'admin/js/govalid-form-builder.js',
				array( 'jquery', 'sortablejs', 'govalid-admin' ),
				GOVALID_QR_VERSION,
				true
			);

			$form_id = 0;
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$fb_nonce = isset( $_GET['_wpnonce'] ) ? sanitize_key( wp_unslash( $_GET['_wpnonce'] ) ) : '';
			if ( $fb_nonce && wp_verify_nonce( $fb_nonce, 'govalid-admin' ) ) {
				// phpcs:ignore WordPress.Security.NonceVerification.Recommended
				$form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : 0;
			}
			wp_add_inline_script(
				'govalid-form-builder',
				'var govalidFormBuilder = ' . wp_json_encode( array(
					'formId'          => $form_id,
					'restUrl'         => rest_url( 'govalid-qr/v1/' ),
					'nonce'           => wp_create_nonce( 'wp_rest' ),
					'builderUrl'      => admin_url( 'admin.php?page=govalid-qr-form-builder' ),
					'submissionsUrl'  => admin_url( 'admin.php?page=govalid-qr-form-submissions' ),
					'i18n'            => array(
						'saved'         => __( 'Form saved!', 'govalid-qr-validator' ),
						'published'     => __( 'Form published!', 'govalid-qr-validator' ),
						'confirmRemove' => __( 'Remove this field?', 'govalid-qr-validator' ),
						'untitled'      => __( 'Untitled Form', 'govalid-qr-validator' ),
						'saving'        => __( 'Saving...', 'govalid-qr-validator' ),
						'copied'        => __( 'Copied!', 'govalid-qr-validator' ),
					),
				) ) . ';',
				'before'
			);
		}

		if ( strpos( $hook, 'govalid-qr-forms' ) !== false || strpos( $hook, 'govalid-qr-form-submissions' ) !== false ) {
			wp_enqueue_script(
				'govalid-forms-admin',
				GOVALID_QR_PLUGIN_URL . 'admin/js/govalid-forms-admin.js',
				array( 'jquery', 'govalid-admin' ),
				GOVALID_QR_VERSION,
				true
			);
		}

		// Submissions page — load Chart.js for statistics.
		if ( strpos( $hook, 'govalid-qr-form-submissions' ) !== false ) {
			wp_enqueue_script(
				'chart-js',
				GOVALID_QR_PLUGIN_URL . 'admin/vendor/chart.umd.min.js',
				array(),
				'4.5.1',
				true
			);
		}

		// Analytics page — load Leaflet, Chart.js, and analytics script.
		if ( strpos( $hook, 'govalid-qr-analytics' ) !== false ) {
			wp_enqueue_style(
				'leaflet-css',
				GOVALID_QR_PLUGIN_URL . 'admin/vendor/leaflet.css',
				array(),
				'1.9.4'
			);

			wp_enqueue_script(
				'leaflet-js',
				GOVALID_QR_PLUGIN_URL . 'admin/vendor/leaflet.js',
				array(),
				'1.9.4',
				true
			);

			wp_enqueue_script(
				'chart-js',
				GOVALID_QR_PLUGIN_URL . 'admin/vendor/chart.umd.min.js',
				array(),
				'4.5.1',
				true
			);

			wp_enqueue_script(
				'leaflet-markercluster',
				GOVALID_QR_PLUGIN_URL . 'admin/vendor/leaflet.markercluster.js',
				array( 'leaflet-js' ),
				'1.4.1',
				true
			);

			wp_enqueue_script(
				'govalid-analytics',
				GOVALID_QR_PLUGIN_URL . 'admin/js/govalid-analytics.js',
				array( 'jquery', 'leaflet-js', 'leaflet-markercluster', 'chart-js', 'govalid-admin' ),
				GOVALID_QR_VERSION,
				true
			);
		}
	}

	/**
	 * Add settings link to plugin list.
	 *
	 * @param array $links Existing links.
	 * @return array
	 */
	public function add_settings_link( array $links ): array {
		$settings_link = sprintf(
			'<a href="%s">%s</a>',
			esc_url( admin_url( 'admin.php?page=govalid-qr' ) ),
			esc_html__( 'Settings', 'govalid-qr-validator' )
		);
		array_unshift( $links, $settings_link );
		return $links;
	}

	/**
	 * Fetch promotional ads from GoValid API (cached for 30 min).
	 *
	 * @return array
	 */
	private function get_promo_ads(): array {
		$cache_key = 'govalid_promo_ads';
		$cached    = get_transient( $cache_key );

		if ( false !== $cached ) {
			return $cached;
		}

		$base_url = GoValid_QR::get_base_url();
		$url      = $base_url . '/api/v1/plugin/ads/?slot=wp_plugin_sidebar&limit=5';

		$response = wp_remote_get( $url, array(
			'timeout'    => 5,
			'user-agent' => 'GoValid-QR-WordPress/' . GOVALID_QR_VERSION,
			'headers'    => array( 'Accept' => 'application/json' ),
		) );

		if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
			// Cache empty result for 5 min so we don't hammer the API on errors.
			set_transient( $cache_key, array(), 5 * MINUTE_IN_SECONDS );
			return array();
		}

		$body = json_decode( wp_remote_retrieve_body( $response ), true );
		$ads  = isset( $body['ads'] ) && is_array( $body['ads'] ) ? $body['ads'] : array();

		set_transient( $cache_key, $ads, 30 * MINUTE_IN_SECONDS );

		return $ads;
	}
}
