<?php
/**
 * PostGate Assets Loader Class
 *
 * Manages plugin assets for frontend, admin pages, the block editor,
 * the Classic Editor (Select2 for multi-select stripe prices),
 * and taxonomy term screens (Select2 for term meta).
 *
 * @package PostGate
 * @subpackage Assets
 * @since 1.0.0
 * @author QodeSphere
 * @license GPL-2.0+
 */

defined( 'ABSPATH' ) || exit;

/**
 * PostGate Assets Loader Class
 *
 * Centralized asset management for the PostGate plugin. Handles enqueuing
 * of CSS and JavaScript files for various contexts including frontend,
 * admin dashboard, block editor, classic editor, and term edit screens.
 *
 * This class ensures proper asset loading with correct dependencies,
 * versioning, and conditional loading based on the current screen context.
 * Manages Select2 integration for multi-select price fields and other
 * interactive components.
 *
 * Responsibilities:
 * - Asset registration and enqueuing for frontend and admin
 * - Conditional loading based on screen context
 * - Script localization for JavaScript data injection
 * - Select2 library integration for admin multi-select fields
 * - Inline CSS injection for admin styling
 *
 * Note: This class focuses solely on asset management. Business logic
 * for lock detection is delegated to PostGate_Content_Lock class.
 *
 * @since 1.0.0
 */
class PostGate_Assets_Loader {

	/**
	 * Initialize the assets loader and hook into WordPress.
	 *
	 * Registers all asset enqueuing hooks for different contexts:
	 * frontend, admin dashboard, settings pages, block editor,
	 * classic editor, and term edit screens.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	public static function init() {
		// Shared admin assets (fonts and common styles) - loaded early
		add_action( 'admin_enqueue_scripts', [ __CLASS__, 'enqueue_shared_admin_assets' ], 5 );

		// Frontend assets (public-facing pages)
		add_action( 'wp_enqueue_scripts', [ __CLASS__, 'enqueue_frontend_assets' ] );

		// Admin dashboard page assets
		add_action( 'admin_enqueue_scripts', [ __CLASS__, 'enqueue_dashboard_assets' ] );

		// Settings page assets
		add_action( 'admin_enqueue_scripts', [ __CLASS__, 'enqueue_settings_assets' ] );

		// Orders management page assets
		add_action( 'admin_enqueue_scripts', [ __CLASS__, 'enqueue_orders_assets' ] );

		// Block editor (Gutenberg) assets
		add_action( 'enqueue_block_editor_assets', [ __CLASS__, 'enqueue_block_editor_assets' ] );

		// Classic editor meta box (post edit screens)
		add_action( 'admin_enqueue_scripts', [ __CLASS__, 'enqueue_classic_editor_assets' ] );

		// Taxonomy term screens (add/edit)
		add_action( 'admin_enqueue_scripts', [ __CLASS__, 'enqueue_term_meta_assets' ] );
	}

	/**
	 * Enqueue shared admin assets (fonts and common styles).
	 *
	 * Loads centralized font assets that are shared across all PostGate admin modules
	 * (dashboard, settings, orders). This prevents duplication of font files
	 * and reduces the plugin build size.
	 *
	 * Only loads on PostGate admin pages to avoid unnecessary asset loading
	 * on other WordPress admin pages.
	 *
	 * Hooked early (priority 5) to ensure fonts load before module-specific assets.
	 *
	 * @since 1.0.1
	 * @param string $hook The current admin page hook.
	 * @return void
	 */
	public static function enqueue_shared_admin_assets( string $hook ): void {
		// Only load on PostGate admin pages
		$postgate_pages = [
			'toplevel_page_postgate-dashboard',
			'postgate_page_postgate-settings',
			'postgate_page_postgate-orders',
		];

		if ( ! in_array( $hook, $postgate_pages, true ) ) {
			return;
		}

		$asset_file = plugin_dir_path( POSTGATE_PLUGIN_FILE ) . 'assets/shared/index.asset.php';
		if ( ! file_exists( $asset_file ) ) {
			return;
		}
		$asset = include $asset_file;

		wp_enqueue_style(
			'postgate-shared',
			plugins_url( 'assets/shared/index.css', POSTGATE_PLUGIN_FILE ),
			[],
			$asset['version']
		);
	}

	/**
	 * Enqueue frontend assets for singular posts and archive pages conditionally.
	 *
	 * Loads JS/CSS for paywall UI in two contexts:
	 * 
	 * 1. Singular posts: When viewing a locked post that is managed by PostGate
	 * 2. Archive pages: When archive_display_mode is 'archive_lock_indicator' 
	 *    AND there are locked posts in the current query
	 *
	 * This ensures assets are only loaded when actually needed for performance.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	public static function enqueue_frontend_assets(): void {
		$should_load_assets = false;

		// Context 1: Singular posts
		if ( is_singular() ) {
			$post_id = get_queried_object_id();
			if ( $post_id ) {
				// Check if this is a purchase success redirect - we need to load assets
				// to display the success banner even if content is now unlocked.
				// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Only checking if assets should load, not performing sensitive operations. Nonce verification happens in PostGate_Access_Redirect_Handler::handle_purchase_success().
				$is_purchase_success = isset( $_GET['postgate_purchase_success'] ) && '1' === sanitize_text_field( wp_unslash( $_GET['postgate_purchase_success'] ) );

				if ( $is_purchase_success ) {
					// Load assets to show success banner
					$should_load_assets = true;
				} else {
					$post_type = get_post_type( $post_id );
					if ( $post_type ) {
						// Use the full lock resolution logic to determine if assets should load
						$should_lock = PostGate_Content_Lock::should_lock_content( $post_id );
						if ( $should_lock ) {
							$should_load_assets = true;
						}
					}
				}
			}
		}
		// Context 2: Archive pages with lock indicator template
		elseif ( ! is_singular() ) {
			// Only load assets if archive display mode is set to show lock indicator
			$archive_display_mode = get_option( 'postgate_archive_display_mode', 'excerpt' );

			if ( 'archive_lock_indicator' === $archive_display_mode ) {
				// Check if there are any locked posts in the current query
				if ( PostGate_Content_Lock::has_locked_posts_in_query() ) {
					$should_load_assets = true;
				}
			}
		}

		// Exit early if assets are not needed
		if ( ! $should_load_assets ) {
			return;
		}

		// Frontend asset manifest (for CSS version/deps)
		$asset_file = plugin_dir_path( POSTGATE_PLUGIN_FILE ) . 'assets/frontend/index.asset.php';
		if ( ! file_exists( $asset_file ) ) {
			return;
		}
		$asset = include $asset_file;

		wp_enqueue_script(
			'postgate-paywall',
			plugins_url( 'assets/frontend/index.js', POSTGATE_PLUGIN_FILE ),
			array_filter(
				$asset['dependencies'],
				function ( $script ) {
					return wp_script_is( $script, 'registered' );
				}
			),
			$asset['version'],
			[ 'in_footer' => true ]
		);

		// Only localize script for singular posts (not needed for archive lock indicator)
		if ( is_singular() ) {
			$post_id = get_queried_object_id();
			wp_localize_script(
				'postgate-paywall',
				'postgateFrontendData',
				[
					'nonce' => wp_create_nonce( 'wp_rest' ),
					'postId' => (string) $post_id,
				]
			);
		}

		wp_enqueue_style(
			'postgate-paywall',
			plugins_url( 'assets/frontend/index.css', POSTGATE_PLUGIN_FILE ),
			array_filter(
				$asset['dependencies'],
				function ( $style ) {
					return wp_style_is( $style, 'registered' );
				}
			),
			$asset['version']
		);
	}

	/**
	 * Enqueue assets for the dashboard admin page.
	 *
	 * Loads CSS and JavaScript specifically for the PostGate dashboard
	 * page in the WordPress admin area.
	 *
	 * @since 1.0.0
	 * @param string $hook The current admin page hook.
	 * @return void
	 */
	public static function enqueue_dashboard_assets( string $hook ): void {
		if ( 'toplevel_page_postgate-dashboard' !== $hook ) {
			return;
		}

		$asset_file = plugin_dir_path( POSTGATE_PLUGIN_FILE ) . 'assets/dashboard/index.asset.php';
		if ( ! file_exists( $asset_file ) ) {
			return;
		}
		$asset = include $asset_file;

		wp_enqueue_script(
			'postgate-dashboard',
			plugins_url( 'assets/dashboard/index.js', POSTGATE_PLUGIN_FILE ),
			array_filter(
				$asset['dependencies'],
				function ( $script ) {
					return wp_script_is( $script, 'registered' );
				}
			),
			$asset['version'],
			[ 'in_footer' => true ]
		);

		wp_enqueue_style(
			'postgate-dashboard',
			plugins_url( 'assets/dashboard/index.css', POSTGATE_PLUGIN_FILE ),
			array_filter(
				$asset['dependencies'],
				function ( $style ) {
					return wp_style_is( $style, 'registered' );
				}
			),
			$asset['version']
		);

		// Localize dashboard data
		wp_localize_script(
			'postgate-dashboard',
			'postgateData',
			[
				'admin_url' => admin_url(),
				'nonce' => wp_create_nonce( 'wp_rest' ),
				'assetsPath' => plugins_url( 'assets/', POSTGATE_PLUGIN_FILE ),
				'version' => POSTGATE_VERSION,
				'nav_links' => [
					'dashboard' => admin_url( 'admin.php?page=postgate-dashboard' ),
					'orders' => admin_url( 'admin.php?page=postgate-orders' ),
					'settings' => admin_url( 'admin.php?page=postgate-settings' ),
				],
			]
		);
	}

	/**
	 * Enqueue assets for the settings admin page.
	 *
	 * Loads CSS and JavaScript specifically for the PostGate settings
	 * page in the WordPress admin area.
	 *
	 * @since 1.0.0
	 * @param string $hook The current admin page hook.
	 * @return void
	 */
	public static function enqueue_settings_assets( string $hook ): void {
		if ( 'postgate_page_postgate-settings' !== $hook ) {
			return;
		}

		$asset_file = plugin_dir_path( POSTGATE_PLUGIN_FILE ) . 'assets/settings/index.asset.php';
		if ( ! file_exists( $asset_file ) ) {
			return;
		}
		$asset = include $asset_file;

		wp_enqueue_script(
			'postgate-settings',
			plugins_url( 'assets/settings/index.js', POSTGATE_PLUGIN_FILE ),
			array_filter(
				$asset['dependencies'],
				function ( $script ) {
					return wp_script_is( $script, 'registered' );
				}
			),
			$asset['version'],
			[ 'in_footer' => true ]
		);

		// Localize currency settings
		wp_localize_script(
			'postgate-settings',
			'postgateData',
			[
				'assetsPath' => plugins_url( 'assets/', POSTGATE_PLUGIN_FILE ),
				'version' => POSTGATE_VERSION,
				'currency' => [
					'code' => get_option( 'postgate_display_currency', 'USD' ),
					'locale' => get_locale(),
				],
				'nonce' => wp_create_nonce( 'wp_rest' ),
			]
		);

		wp_enqueue_style(
			'postgate-settings',
			plugins_url( 'assets/settings/index.css', POSTGATE_PLUGIN_FILE ),
			array_filter(
				$asset['dependencies'],
				function ( $style ) {
					return wp_style_is( $style, 'registered' );
				}
			),
			$asset['version']
		);
	}

	/**
	 * Enqueue assets for the orders management page.
	 *
	 * Loads JavaScript and CSS for the orders management screen with DataViews.
	 *
	 * @since 1.0.0
	 * @param string $hook_suffix The current admin page hook.
	 * @return void
	 */
	public static function enqueue_orders_assets( string $hook_suffix ): void {
		if ( 'postgate_page_postgate-orders' !== $hook_suffix ) {
			return;
		}

		$asset_file = plugin_dir_path( POSTGATE_PLUGIN_FILE ) . 'assets/orders/index.asset.php';
		if ( ! file_exists( $asset_file ) ) {
			return;
		}
		$asset = include $asset_file;

		wp_enqueue_script(
			'postgate-orders',
			plugins_url( 'assets/orders/index.js', POSTGATE_PLUGIN_FILE ),
			array_filter(
				$asset['dependencies'],
				function ( $script ) {
					return wp_script_is( $script, 'registered' );
				}
			),
			$asset['version'],
			[ 'in_footer' => true ]
		);

		wp_enqueue_style(
			'postgate-orders',
			plugins_url( 'assets/orders/style-index.css', POSTGATE_PLUGIN_FILE ),
			array_filter(
				$asset['dependencies'],
				function ( $style ) {
					return wp_style_is( $style, 'registered' );
				}
			),
			$asset['version']
		);

		// Pass admin URL to JavaScript
		wp_localize_script(
			'postgate-orders',
			'postgateData',
			[
				'assetsPath' => plugins_url( 'assets/', POSTGATE_PLUGIN_FILE ),
				'version' => POSTGATE_VERSION,
				'adminUrl' => admin_url( 'admin.php' ),
				'nonce' => wp_create_nonce( 'wp_rest' ),
				'nav_links' => [
					'dashboard' => admin_url( 'admin.php?page=postgate-dashboard' ),
					'orders' => admin_url( 'admin.php?page=postgate-orders' ),
					'settings' => admin_url( 'admin.php?page=postgate-settings' ),
				],
			]
		);
	}

	/**
	 * Enqueue assets for the block editor (Gutenberg).
	 *
	 * Loads block editor specific assets for PostGate meta fields.
	 * Assets are always loaded for public post types, allowing users
	 * to configure PostGate settings even if the post type is not
	 * locked by default in global settings.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	public static function enqueue_block_editor_assets(): void {
		if ( ! function_exists( 'get_current_screen' ) ) {
			return;
		}
		$screen = get_current_screen();
		if ( ! $screen ) {
			return;
		}
		if ( $screen->base !== 'post' && $screen->base !== 'post-new' ) {
			return;
		}

		$post_type = isset( $screen->post_type ) ? (string) $screen->post_type : '';
		if ( $post_type === '' ) {
			return;
		}

		// Check if this is a public post type
		$post_type_object = get_post_type_object( $post_type );
		if ( ! $post_type_object || ! $post_type_object->public ) {
			return;
		}

		$asset_file = plugin_dir_path( POSTGATE_PLUGIN_FILE ) . 'assets/editor/index.asset.php';
		if ( ! file_exists( $asset_file ) ) {
			return;
		}
		$asset = include $asset_file;

		wp_enqueue_script(
			'postgate-block-editor',
			plugins_url( 'assets/editor/index.js', POSTGATE_PLUGIN_FILE ),
			array_filter(
				$asset['dependencies'],
				function ( $script ) {
					return wp_script_is( $script, 'registered' );
				}
			),
			$asset['version'],
			true
		);
	}

	/**
	 * Enqueue assets for the classic editor post edit screens.
	 *
	 * Loads Select2 and related assets for multi-select price fields
	 * in PostGate meta boxes when using the classic editor.
	 * Assets are always loaded for public post types, allowing users
	 * to configure PostGate settings even if the post type is not
	 * locked by default in global settings.
	 *
	 * @since 1.0.0
	 * @param string $hook The current admin page hook.
	 * @return void
	 */
	public static function enqueue_classic_editor_assets( string $hook ): void {
		if ( ! function_exists( 'get_current_screen' ) ) {
			return;
		}
		$screen = get_current_screen();
		if ( ! $screen ) {
			return;
		}

		// Only on post edit/create screens (classic)
		if ( $screen->base !== 'post' && $screen->base !== 'post-new' ) {
			return;
		}
		// Skip when block editor is active
		if ( method_exists( $screen, 'is_block_editor' ) && $screen->is_block_editor() ) {
			return;
		}

		$post_type = isset( $screen->post_type ) ? (string) $screen->post_type : '';
		if ( $post_type === '' ) {
			return;
		}

		// Check if this is a public post type
		$post_type_object = get_post_type_object( $post_type );
		if ( ! $post_type_object || ! $post_type_object->public ) {
			return;
		}

		self::enqueue_select2_and_init( __( 'Select one or more prices…', 'postgate' ) );
		self::enqueue_admin_inline_css();
	}

	/**
	 * Enqueue assets for taxonomy term add/edit screens.
	 *
	 * Loads Select2 and related assets for multi-select price fields
	 * on term edit screens. Assets are always loaded for public taxonomies,
	 * allowing users to configure PostGate settings at the term level
	 * even if the associated post types are not locked by default.
	 *
	 * @since 1.0.0
	 * @param string $hook The current admin page hook.
	 * @return void
	 */
	public static function enqueue_term_meta_assets( string $hook ): void {
		if ( ! function_exists( 'get_current_screen' ) ) {
			return;
		}
		$screen = get_current_screen();
		if ( ! $screen ) {
			return;
		}

		// Taxonomy screens: list/add (edit-tags), edit single (term)
		if ( $screen->base !== 'edit-tags' && $screen->base !== 'term' ) {
			return;
		}

		$taxonomy = isset( $screen->taxonomy ) ? (string) $screen->taxonomy : '';
		if ( $taxonomy === '' ) {
			return;
		}

		// Check if this is a public taxonomy
		$taxonomy_object = get_taxonomy( $taxonomy );
		if ( ! $taxonomy_object || empty( $taxonomy_object->show_ui ) ) {
			return;
		}

		self::enqueue_select2_and_init( __( 'Select one or more prices…', 'postgate' ) );
		self::enqueue_admin_inline_css();
	}

	/**
	 * Enqueue Select2 library and initialize it for PostGate product fields.
	 *
	 * Loads the Select2 jQuery plugin and initializes it on the element with
	 * the ID "postgate_product_ids" (multi-select product assignment field).
	 *
	 * @since 1.0.0
	 * @param string $placeholder The placeholder text for the Select2 field.
	 * @return void
	 */
	private static function enqueue_select2_and_init( string $placeholder ) {
		$js_url = plugins_url( 'assets/vendor/select2/select2.min.js', POSTGATE_PLUGIN_FILE );
		$css_url = plugins_url( 'assets/vendor/select2/select2.min.css', POSTGATE_PLUGIN_FILE );

		wp_register_script( 'postgate-select2', $js_url, [ 'jquery' ], '4.1.0-rc.0', true );
		wp_register_style( 'postgate-select2', $css_url, [], '4.1.0-rc.0' );

		wp_enqueue_script( 'postgate-select2' );
		wp_enqueue_style( 'postgate-select2' );

		$placeholder_esc = esc_js( $placeholder );
		$init_js = "
			jQuery(function($){
				var \$productField = $('#postgate_product_ids');
				if (!\$productField.length || !$.fn.select2) return;
				\$productField.select2({
					width: '100%',
					placeholder: '{$placeholder_esc}',
					allowClear: true
				});
			});
		";
		wp_add_inline_script( 'postgate-select2', $init_js, 'after' );
	}

	/**
	 * Enqueue inline CSS for PostGate admin styling.
	 *
	 * Adds custom CSS for PostGate field spacing and Select2 appearance
	 * improvements to maintain consistent styling across admin screens.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	private static function enqueue_admin_inline_css() {
		$inline_css = "
			.postgate-field + .postgate-field { margin: 10px 0; }
			.postgate-small { font-size: 12px; color: #6b7280; }
			.postgate-field strong { display: inline-block; margin-bottom: 10px; }
			.postgate-field input, .postgate-field select { margin: 0 !important; }

			/* Ensure the Select2 container fills its wrapper and chips wrap inside */
			.postgate-select2-wrap .select2-container { width: 100% !important; display: block; }
			.select2-container--default .select2-selection--multiple {
				min-height: 36px;
				box-sizing: border-box;
				border-color: #8c8f94;
				padding: 4px 4px 2px 4px;
			}
			.select2-container--default .select2-selection--multiple .select2-selection__rendered {
				display: flex;
				flex-wrap: wrap;
				align-items: center;
				gap: 4px;
				margin: 0;
				padding: 0 4px 2px 0;
			}
			.select2-container--default .select2-selection--multiple .select2-selection__choice {
				padding: 0 10px 0 20px;
				margin: 2px 0 0 0;
			}
		";

		wp_register_style( 'postgate-admin-inline', false, [], '1.0.0' );
		wp_enqueue_style( 'postgate-admin-inline' );
		wp_add_inline_style( 'postgate-admin-inline', $inline_css );
	}
}
