<?php
/**
 * Handles script and style registration and enqueuing.
 *
 * @package PDFDraft_WooCommerce
 */

namespace PDFDraft\Woocommerce\Core;

use PDFDraft\Traits\Hooks;
use PDFDraft\Woocommerce\Admin\Settings\Registry;

/**
 * Manages plugin asset registration and enqueuing.
 */
class Assets {

	use Hooks;

	/**
	 * Settings section registry (provides localized data for the JS bundle).
	 *
	 * @var Registry
	 */
	private Registry $settingsRegistry;

	/**
	 * @param Registry $settingsRegistry Settings section registry.
	 */
	public function __construct( Registry $settingsRegistry ) {
		$this->settingsRegistry = $settingsRegistry;
	}

	/**
	 * Register WordPress hooks for assets.
	 *
	 * @return void
	 */
	public function initHooks() {
		// Hook names must match PDFDraft\ScriptStyle and PDFDraft\Editor (underscores, not colons).
		$this->addFilter( 'pdfdraft_scripts', array( $this, 'registerScripts' ) );
		$this->addAction( 'pdfdraft_editor_after_enqueue_scripts', array( $this, 'enqueueScripts' ) );
		$this->addAction( 'pdfdraft_scripts_registered', array( $this, 'localizeScripts' ) );
		$this->addAction( 'admin_enqueue_scripts', array( $this, 'ensureSelectWooCompat' ), 1 );
		$this->addAction( 'pdfdraft_settings_page_enqueue_scripts', array( $this, 'enqueueSettingsPageScript' ) );
		$this->addFilter( 'pdfdraft_editor_preview_dummy_data', array( $this, 'applyInvoicePrefixSuffixToPreview' ) );
	}

	/**
	 * Ensure selectWoo exists for third-party admin scripts (e.g., YITH).
	 *
	 * @return void
	 */
	public function ensureSelectWooCompat(): void {
		$select_woo_stub = "if ( typeof jQuery !== 'undefined' && typeof jQuery.fn.selectWoo !== 'function' ) { jQuery.fn.selectWoo = typeof jQuery.fn.select2 === 'function' ? jQuery.fn.select2 : function() { return this; }; }";
		wp_add_inline_script( 'jquery', $select_woo_stub, 'after' );
	}

	/**
	 * Apply invoice prefix/suffix to the preview dummy data so the Preview button
	 * shows the invoice_number in the same format as the real PDF.
	 *
	 * @param array $data Dummy preview data.
	 * @return array Modified dummy preview data.
	 */
	public function applyInvoicePrefixSuffixToPreview( array $data ): array {
		$option_key = (string) apply_filters( 'pdfdraft_pdf_invoices_for_woocommerce_settings_option_key', 'pdfdraft_pdf_invoices_for_woocommerce_settings' );
		$settings   = get_option( $option_key, array() );
		$prefix     = (string) ( $settings['general']['invoice_settings']['invoice_prefix'] ?? '' );
		$suffix     = (string) ( $settings['general']['invoice_settings']['invoice_suffix'] ?? '' );

		if ( '' !== $prefix || '' !== $suffix ) {
			$raw                    = isset( $data['invoice_number'] ) ? (string) $data['invoice_number'] : '1042';
			$data['invoice_number'] = $prefix . $raw . $suffix;
		}

		return $data;
	}

	/**
	 * Localize invoice download scripts with REST data.
	 *
	 * @return void
	 */
	public function localizeScripts() {
		$isDev = defined( 'PDFDRAFT_IS_DEVELOPMENT' ) && PDFDRAFT_IS_DEVELOPMENT;
		wp_localize_script(
			'pdfdraft-woocommerce',
			'__PDFDRAFT_PDF_INVOICES_FOR_WOOCOMMERCE__',
			array(
				'pluginUrl' => untrailingslashit( PDFDRAFT_PDF_INVOICES_FOR_WOOCOMMERCE_PLUGIN_URL ),
			)
		);

		$data  = array(
			'downloadUrl' => esc_url( rest_url( 'pdfdraft-pdf-invoices-for-woocommerce/v1/orders/' ) ),
			'nonce'       => wp_create_nonce( 'wp_rest' ),
			'debug'       => $isDev,
			'i18n'        => array(
				'errorDownloadFailed'      => esc_html__( 'Download failed. Please try again.', 'pdfdraft-pdf-invoices-for-woocommerce' ),
				'removeStoredInvoiceLabel' => esc_html__( 'Remove stored invoice', 'pdfdraft-pdf-invoices-for-woocommerce' ),
				'confirmDeleteInvoice'     => esc_html__( 'Remove the stored invoice file and all invoice data for this order? This cannot be undone.', 'pdfdraft-pdf-invoices-for-woocommerce' ),
				'errorDeleteFailed'        => esc_html__( 'Could not remove the invoice. Please try again.', 'pdfdraft-pdf-invoices-for-woocommerce' ),
			),
		);
		$data  = $this->applyFilters( 'pdfdraft_pdf_invoices_for_woocommerce_invoice_download_localize_scripts', $data );
		$data  = apply_filters( 'pdfdraft_pdf_invoices_for_woocommerce_invoice_download_script_localize', $data );
		// Back-compat: older colon-style hook name (prefer underscores above).
		$data = apply_filters( 'pdfdraft:woocommerce-invoice-download:localize:scripts', $data );
		wp_localize_script(
			'pdfdraft-woocommerce-invoice-download',
			'__PDFDRAFT_PDF_INVOICES_FOR_WOOCOMMERCE_INVOICE_DOWNLOAD__',
			$data
		);
	}

	/**
	 * Register plugin scripts with their dependencies.
	 *
	 * @param array $scripts Registered scripts array.
	 * @return array Modified scripts array.
	 */
	public function registerScripts( $scripts ) {
		$isDev = defined( 'PDFDRAFT_IS_DEVELOPMENT' ) && PDFDRAFT_IS_DEVELOPMENT;

		// In dev mode webpack splits a separate runtime chunk (runtimeChunk: 'single')
		// that must be loaded before any entry point for HMR / React Fast Refresh to work.
		if ( $isDev ) {
			$scripts['woocommerce-runtime'] = array(
				'src'     => 'http://localhost:8889/runtime.js',
				'deps'    => array(),
				'version' => md5( time() . wp_rand( 0, 1000 ) ),
			);
		}

		$editorAssetPath = PDFDRAFT_PDF_INVOICES_FOR_WOOCOMMERCE_PLUGIN_DIR . '/dist/woocommerce.asset.php';
		$editorAsset     = file_exists( $editorAssetPath ) ? require $editorAssetPath : array(
			'dependencies' => array(),
			'version'      => PDFDRAFT_PDF_INVOICES_FOR_WOOCOMMERCE_VERSION,
		);

		$editorAssetDeps = array_filter(
			$editorAsset['dependencies'],
			static fn( $dep ) => 'wp-react-refresh-runtime' !== $dep
		);

		$editorDeps = array_merge(
			$editorAssetDeps,
			array( 'pdfdraft-editor' )
		);

		if ( $isDev ) {
			$editorDeps[] = 'pdfdraft-woocommerce-runtime';
		}

		$scripts['woocommerce'] = array(
			'src'     => $this->getScriptSrc(),
			'deps'    => array_values( array_unique( $editorDeps ) ),
			'version' => $editorAsset['version'],
			'i18n'    => true,
		);

		$invoiceDownloadAssetPath = PDFDRAFT_PDF_INVOICES_FOR_WOOCOMMERCE_PLUGIN_DIR . '/dist/invoice-download.asset.php';
		$invoiceDownloadAsset     = file_exists( $invoiceDownloadAssetPath ) ? require $invoiceDownloadAssetPath : array(
			'dependencies' => array(),
			'version'      => PDFDRAFT_PDF_INVOICES_FOR_WOOCOMMERCE_VERSION,
		);

		$invoiceDownloadDeps = array_filter(
			$invoiceDownloadAsset['dependencies'],
			static fn( $dep ) => 'wp-react-refresh-runtime' !== $dep
		);

		$scripts['woocommerce-invoice-download'] = array(
			'src'     => $this->getPluginBaseUrl() . '/dist/invoice-download.js',
			'deps'    => $invoiceDownloadDeps,
			'version' => $invoiceDownloadAsset['version'],
		);

		$settingsAssetPath = PDFDRAFT_PDF_INVOICES_FOR_WOOCOMMERCE_PLUGIN_DIR . '/dist/woocommerce-settings.asset.php';
		$settingsAsset     = file_exists( $settingsAssetPath ) ? require $settingsAssetPath : array(
			'dependencies' => array(),
			'version'      => PDFDRAFT_PDF_INVOICES_FOR_WOOCOMMERCE_VERSION,
		);

		// Filter out dev-only webpack artifacts that aren't registered WP scripts.
		$settingsAssetDeps = array_filter(
			$settingsAsset['dependencies'],
			static fn( $dep ) => 'wp-react-refresh-runtime' !== $dep
		);

		$settingsDeps = array_merge(
			$settingsAssetDeps,
			array( 'pdfdraft-core', 'pdfdraft-ui' )
		);

		// In dev mode the runtime chunk must load before the settings entry point.
		if ( $isDev ) {
			$settingsDeps[] = 'pdfdraft-woocommerce-runtime';
		}

		$scripts['woocommerce-settings'] = $this->applyFilters(
			'pdfdraft_pdf_invoices_for_woocommerce_settings_script_config',
			array(
				'src'     => $this->getSettingsScriptSrc(),
				'deps'    => $settingsDeps,
				'version' => $settingsAsset['version'],
				'i18n'    => true,
			)
		);

		return $scripts;
	}

	/**
	 * Get the editor script source URL.
	 *
	 * @return string Script URL.
	 */
	private function getScriptSrc() {
		return defined( 'PDFDRAFT_IS_DEVELOPMENT' ) && PDFDRAFT_IS_DEVELOPMENT
			? 'http://localhost:8889/woocommerce.js'
			: $this->getPluginBaseUrl() . '/dist/woocommerce.js';
	}

	/**
	 * Get the settings script source URL.
	 *
	 * @return string Script URL.
	 */
	private function getSettingsScriptSrc(): string {
		return defined( 'PDFDRAFT_IS_DEVELOPMENT' ) && PDFDRAFT_IS_DEVELOPMENT
			? 'http://localhost:8889/woocommerce-settings.js'
			: $this->getPluginBaseUrl() . '/dist/woocommerce-settings.js';
	}

	/**
	 * Get plugin base URL without trailing slash.
	 *
	 * @return string
	 */
	private function getPluginBaseUrl(): string {
		return untrailingslashit( PDFDRAFT_PDF_INVOICES_FOR_WOOCOMMERCE_PLUGIN_URL );
	}

	/**
	 * Enqueue the WooCommerce settings script on the unified PDFDraft settings page.
	 *
	 * Called via the `pdfdraft_settings_page_enqueue_scripts` action, which is fired
	 * by the main plugin only when the core settings page is active.
	 *
	 * @return void
	 */
	public function enqueueSettingsPageScript(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		wp_enqueue_script( 'pdfdraft-woocommerce-settings' );
		wp_localize_script(
			'pdfdraft-woocommerce-settings',
			'__PDFDRAFT_PDF_INVOICES_FOR_WOOCOMMERCE_SETTINGS__',
			$this->settingsRegistry->getLocalizedData()
		);
		wp_set_script_translations(
			'pdfdraft-woocommerce-settings',
			'pdfdraft-pdf-invoices-for-woocommerce',
			PDFDRAFT_PDF_INVOICES_FOR_WOOCOMMERCE_PLUGIN_DIR . '/languages'
		);
	}

	/**
	 * Enqueue the WooCommerce editor scripts.
	 *
	 * @return void
	 */
	public function enqueueScripts() {
		wp_enqueue_script( 'pdfdraft-woocommerce' );
		wp_set_script_translations(
			'pdfdraft-woocommerce',
			'pdfdraft-pdf-invoices-for-woocommerce',
			PDFDRAFT_PDF_INVOICES_FOR_WOOCOMMERCE_PLUGIN_DIR . '/languages'
		);
	}

	/**
	 * Enqueue the invoice download script and style on the frontend.
	 *
	 * @return void
	 */
	public function enqueueInvoiceDownloadScriptStyle() {
		$assetPath = PDFDRAFT_PDF_INVOICES_FOR_WOOCOMMERCE_PLUGIN_DIR . '/dist/invoice-download.asset.php';
		$asset     = file_exists( $assetPath ) ? require $assetPath : array(
			'dependencies' => array(),
			'version'      => PDFDRAFT_PDF_INVOICES_FOR_WOOCOMMERCE_VERSION,
		);

		if ( ! wp_script_is( 'pdfdraft-pdf-invoices-for-woocommerce-invoice-download', 'registered' ) ) {
			$deps = array_filter(
				$asset['dependencies'],
				static fn( $dep ) => 'wp-react-refresh-runtime' !== $dep
			);

			wp_register_script(
				'pdfdraft-pdf-invoices-for-woocommerce-invoice-download',
				$this->getPluginBaseUrl() . '/dist/invoice-download.js',
				$deps,
				$asset['version'],
				true
			);

			$data = array(
				'downloadUrl' => esc_url( rest_url( 'pdfdraft-pdf-invoices-for-woocommerce/v1/orders/' ) ),
				'nonce'       => wp_create_nonce( 'wp_rest' ),
				'debug'       => ( defined( 'PDFDRAFT_IS_DEVELOPMENT' ) && PDFDRAFT_IS_DEVELOPMENT ),
				'i18n'        => array(
					'errorDownloadFailed'      => esc_html__( 'Download failed. Please try again.', 'pdfdraft-pdf-invoices-for-woocommerce' ),
					'removeStoredInvoiceLabel' => esc_html__( 'Remove stored invoice', 'pdfdraft-pdf-invoices-for-woocommerce' ),
					'confirmDeleteInvoice'     => esc_html__( 'Remove the stored invoice file and all invoice data for this order? This cannot be undone.', 'pdfdraft-pdf-invoices-for-woocommerce' ),
					'errorDeleteFailed'        => esc_html__( 'Could not remove the invoice. Please try again.', 'pdfdraft-pdf-invoices-for-woocommerce' ),
				),
			);
			$data = apply_filters( 'pdfdraft_pdf_invoices_for_woocommerce_invoice_download_script_localize', $data );

			wp_localize_script(
				'pdfdraft-pdf-invoices-for-woocommerce-invoice-download',
				'__PDFDRAFT_PDF_INVOICES_FOR_WOOCOMMERCE_INVOICE_DOWNLOAD__',
				$data
			);
		}

		wp_enqueue_script( 'pdfdraft-pdf-invoices-for-woocommerce-invoice-download' );

		$invoiceCssPath = PDFDRAFT_PDF_INVOICES_FOR_WOOCOMMERCE_PLUGIN_DIR . '/dist/invoice-download.css';
		$invoiceCssVer  = file_exists( $invoiceCssPath )
			? (string) filemtime( $invoiceCssPath )
			: $asset['version'];

		wp_enqueue_style(
			'pdfdraft-pdf-invoices-for-woocommerce-invoice-download-button',
			$this->getPluginBaseUrl() . '/dist/invoice-download.css',
			array(),
			$invoiceCssVer
		);
	}
}
