<?php
/**
 * Assets helper.
 *
 * Provides helpers for building plugin asset URLs/paths, versioning by filemtime,
 * and enqueueing scripts/styles (including inline CSS from a file).
 *
 * @package Simplyin\Simplyin_W_Plugin
 */

declare(strict_types=1);

namespace Simplyin\Simplyin_W_Plugin;

/**
 * Class Assets
 *
 * @package Simplyin\Simplyin_W_Plugin
 */
final class Assets {

	/**
	 * Plugin base directory path (with trailing slash).
	 *
	 * @var string
	 */
	private string $base_dir;

	/**
	 * Plugin base URL (with trailing slash).
	 *
	 * @var string
	 */
	private string $base_url;

	/**
	 * Fallback version when file doesn't exist or filemtime cannot be read.
	 *
	 * @var string
	 */
	private string $fallback_version;

	/**
	 * Constructor.
	 *
	 * @param string $plugin_file       Main plugin file path (typically __FILE__).
	 * @param string $fallback_version  Fallback version string.
	 */
	public function __construct( string $plugin_file, string $fallback_version = '1.0.0' ) {
		$this->base_dir         = trailingslashit( plugin_dir_path( $plugin_file ) );
		$this->base_url         = trailingslashit( plugin_dir_url( $plugin_file ) );
		$this->fallback_version = $fallback_version;
	}

	/**
	 * Build full asset URL.
	 *
	 * @param string $relative Relative path within the plugin.
	 * @return string
	 */
	public function url( string $relative ): string {
		return $this->base_url . ltrim( $relative, "/\\\t\n\r\0\x0B" );
	}

	/**
	 * Build full asset filesystem path.
	 *
	 * @param string $relative Relative path within the plugin.
	 * @return string
	 */
	public function path( string $relative ): string {
		return $this->base_dir . ltrim( $relative, "/\\\t\n\r\0\x0B" );
	}

	/**
	 * Version for asset based on file modification time.
	 *
	 * @param string $relative Relative path within the plugin.
	 * @return string
	 */
	public function ver( string $relative ): string {
		$path = $this->path( $relative );

		if ( true === is_file( $path ) ) {
			$mtime = filemtime( $path );

			if ( true === is_int( $mtime ) && 0 < $mtime ) {
				return (string) $mtime;
			}
		}

		return $this->fallback_version;
	}

	/**
	 * Enqueue script with versioning.
	 *
	 * @param string $handle   Script handle.
	 * @param string $relative Relative path within the plugin.
	 * @param array  $deps     Dependencies.
	 * @param bool   $in_footer Whether to load in footer.
	 * @return void
	 */
	public function enqueue_script( string $handle, string $relative, array $deps = array(), bool $in_footer = true ): void {
		wp_enqueue_script(
			$handle,
			$this->url( $relative ),
			$deps,
			$this->ver( $relative ),
			$in_footer
		);
	}

	/**
	 * Enqueue stylesheet with versioning.
	 *
	 * @param string $handle   Style handle.
	 * @param string $relative Relative path within the plugin.
	 * @param array  $deps     Dependencies.
	 * @param string $media    Media.
	 * @return void
	 */
	public function enqueue_style( string $handle, string $relative, array $deps = array(), string $media = 'all' ): void {
		wp_enqueue_style(
			$handle,
			$this->url( $relative ),
			$deps,
			$this->ver( $relative ),
			$media
		);
	}

	/**
	 * Enqueue inline CSS from a file (registers a "virtual" stylesheet handle).
	 *
	 * Useful when you want to avoid optimizers/caches transforming the CSS file request.
	 *
	 * @param string $handle   Style handle.
	 * @param string $relative Relative path within the plugin.
	 * @param array  $deps     Dependencies.
	 * @param string $media    Media.
	 * @return void
	 */
	public function enqueue_inline_style_from_file( string $handle, string $relative, array $deps = array(), string $media = 'all' ): void {
		wp_register_style(
			$handle,
			false,
			$deps,
			$this->ver( $relative ),
			$media
		);

		wp_enqueue_style( $handle );

		$path = $this->path( $relative );

		if ( true !== is_file( $path ) ) {
			return;
		}

		$css = file_get_contents( $path );

		if ( true !== is_string( $css ) || '' === $css ) {
			return;
		}

		wp_add_inline_style( $handle, $css );
	}
}
