<?php
/**
 * Asset registration and enqueueing class.
 *
 * Reads the Vite manifest (assets/.vite/manifest.json) in production
 * and falls back to direct paths in development mode.
 *
 * @package CyyWordpress
 */

if ( ! class_exists( 'CyyWordpress_Assets' ) ) :

	/**
	 * Handles all script / style enqueueing for the theme.
	 */
	class CyyWordpress_Assets {

		/** Absolute path to the compiled assets directory. */
		private const ASSETS_DIR = __DIR__ . '/../assets';

		/** URL to the compiled assets directory. */
		private static string $assets_url = '';

		/** Parsed Vite manifest. */
		private static array $manifest = [];

		/**
		 * Registers hooks.
		 */
		public static function init(): void {
			self::$assets_url = get_template_directory_uri() . '/assets';
			self::load_manifest();

			add_action( 'wp_enqueue_scripts',    array( static::class, 'enqueue_frontend' ) );
			add_action( 'admin_enqueue_scripts', array( static::class, 'enqueue_admin' ) );
			add_filter( 'script_loader_tag',     array( static::class, 'add_defer_attr' ), 10, 2 );
		}

		/**
		 * Loads and caches the Vite manifest if it exists.
		 */
		private static function load_manifest(): void {
			$manifest_path = self::ASSETS_DIR . '/.vite/manifest.json';

			if ( file_exists( $manifest_path ) ) {
				$json = file_get_contents( $manifest_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions
				if ( $json ) {
					self::$manifest = json_decode( $json, true ) ?? [];
				}
			}
		}

		/**
		 * Returns the hashed asset URL from the Vite manifest
		 * or falls back to the raw path.
		 *
		 * @param string $entry The entry key (e.g. "src/ts/main.ts").
		 * @param string $type  'js' or 'css'.
		 */
		private static function asset_url( string $entry, string $type = 'js' ): string {
			if ( ! empty( self::$manifest[ $entry ][ 'file' ] ) ) {
				return self::$assets_url . '/' . self::$manifest[ $entry ][ 'file' ];
			}

			// Dev fallback.
			return self::$assets_url . "/$type/" . basename( $entry, '.ts' ) . '.' . $type;
		}

		/**
		 * Returns the filemtime-based version string for a local file,
		 * used for cache-busting in development.
		 *
		 * @param string $path Relative path from assets dir.
		 */
		private static function file_version( string $path ): string {
			$abs = self::ASSETS_DIR . '/' . ltrim( $path, '/' );
			return file_exists( $abs ) ? (string) filemtime( $abs ) : _S_VERSION;
		}

		/**
		 * Enqueue front-end styles and scripts.
		 */
		public static function enqueue_frontend(): void {
			// Main CSS.
			$css_url = self::asset_url( 'src/ts/main.ts', 'css' );
			wp_enqueue_style(
				'cyywordpress-main',
				$css_url,
				array(),
				_S_VERSION
			);
			wp_style_add_data( 'cyywordpress-main', 'rtl', 'replace' );

			// Legacy style.css (theme header required by WP).
			wp_enqueue_style(
				'cyywordpress-style',
				get_stylesheet_uri(),
				array( 'cyywordpress-main' ),
				_S_VERSION
			);

			// Main JS.
			$js_url = self::asset_url( 'src/ts/main.ts', 'js' );
			wp_enqueue_script(
				'cyywordpress-main',
				$js_url,
				array(),
				_S_VERSION,
				true
			);

			// Font Awesome (local).
			wp_enqueue_style(
				'font-awesome',
				get_template_directory_uri() . '/node_modules/@fortawesome/fontawesome-free/css/all.min.css',
				array(),
				'6.5.2'
			);

			// Comment reply: only when needed.
			if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
				wp_enqueue_script( 'comment-reply' );
			}
		}

		/**
		 * Enqueue admin / Customizer scripts.
		 */
		public static function enqueue_admin(): void {
			// Customizer preview script is handled via customize_preview_init hook.
		}

		/**
		 * Add `defer` attribute to all theme JS files.
		 *
		 * @param string $tag    The <script> HTML tag.
		 * @param string $handle The registered script handle.
		 */
		public static function add_defer_attr( string $tag, string $handle ): string {
			$defer_handles = array( 'cyywordpress-main' );

			if ( in_array( $handle, $defer_handles, true ) ) {
				return str_replace( ' src=', ' defer src=', $tag );
			}

			return $tag;
		}
	}

endif;
