<?php

namespace WarrantyCart\Frontend;

use WarrantyCart\Core\Coverage;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Frontend Assets Class
 */
class Assets {

	/**
	 * Constructor
	 */
	public function __construct() {
		\add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts_styles' ) );
	}

	/**
	 * Enqueue frontend scripts
	 *
	 * Loads JavaScript and CSS assets for the frontend warranty selector.
	 */
	public function enqueue_scripts_styles(): void {
		/**
		 * Filter whether to enqueue frontend assets
		 *
		 * @param bool $enqueue Whether to enqueue assets.
		 */
		$enqueue_assets = \apply_filters( 'warranty_cart_enqueue_frontend_assets', true );

		if ( ! $enqueue_assets || ! $this->should_enqueue_assets() ) {
			return;
		}

		$frontend_asset_file = sprintf( '%s/build/frontend.asset.php', WARRANTY_CART_PATH );
		if ( ! file_exists( $frontend_asset_file ) ) {
			return;
		}

		$frontend_asset = require $frontend_asset_file;

		/**
		 * Filter frontend asset dependencies
		 *
		 * @param array $dependencies Asset dependencies.
		 */
		$frontend_asset_deps = \apply_filters(
			'warranty_cart_frontend_asset_dependencies',
			array_merge( $frontend_asset['dependencies'], array( 'jquery' ) )
		);

		$frontend_asset_version = $frontend_asset['version'] ?? WARRANTY_CART_VERSION;

		/**
		 * Filter frontend script handle
		 *
		 * @param string $handle Script handle.
		 */
		$frontend_script_handle = \apply_filters( 'warranty_cart_frontend_script_handle', 'warranty-frontend' );

		\wp_enqueue_script(
			$frontend_script_handle,
			WARRANTY_CART_URL . 'build/frontend.js',
			$frontend_asset_deps,
			$frontend_asset_version,
			true
		);

		/**
		 * Filter frontend style handle
		 *
		 * @param string $handle Style handle.
		 */
		$frontend_style_handle = \apply_filters( 'warranty_cart_frontend_style_handle', 'warranty-frontend' );

		\wp_enqueue_style(
			$frontend_style_handle,
			WARRANTY_CART_URL . 'build/style-frontend.css',
			array(),
			$frontend_asset_version
		);

		// Enqueue checkout styles
		\wp_enqueue_style(
			'warranty-checkout',
			WARRANTY_CART_URL . 'assets/css/warranty-checkout.css',
			array(),
			WARRANTY_CART_VERSION
		);

		\wp_set_script_translations( 'warranty-frontend', 'warranty-cart' );

		/**
		 * Filter frontend script localization data
		 *
		 * @param array $data Localization data.
		 */
		$localization_data = \apply_filters(
			'warranty_cart_frontend_script_localization',
			array(
				'root'     => \esc_url_raw( \rest_url() ),
				'nonce'    => \wp_create_nonce( 'wp_rest' ),

				/*
				 * The store's currency symbol.
				 *
				 * The running total and the selected-items list were built in
				 * JavaScript with a hardcoded '€', while every price beside
				 * them is rendered by wc_price() in the store's own currency.
				 * A dollar store showed "$39.00" in the card and "€39.00" in
				 * the total, on the same screen.
				 */
				'currency' => \html_entity_decode( \get_woocommerce_currency_symbol(), ENT_QUOTES, 'UTF-8' ),
			)
		);

		\wp_localize_script(
			'warranty-frontend',
			'warrantyCartApiSettings',
			$localization_data
		);

		/**
		 * Action after enqueuing frontend assets
		 */
		\do_action( 'warranty_cart_after_enqueue_frontend_assets' );
	}


	/**
	 * Check if assets should be enqueued
	 *
	 * Determines whether to load frontend assets based on current page content.
	 *
	 * @return bool True if assets should be loaded, false otherwise.
	 */
	private function should_enqueue_assets(): bool {
		global $post;

		/**
		 * Filter whether assets should be enqueued on current page
		 *
		 * @param bool         $enqueue Whether to enqueue assets.
		 * @param WP_Post|null $post    Current post object.
		 */
		$should_enqueue = \apply_filters( 'warranty_cart_should_enqueue_frontend_assets', null, $post );

		if ( null !== $should_enqueue ) {
			return (bool) $should_enqueue;
		}

		// Enqueue on pages with the shortcode.
		//
		// The tag comes from Shortcode::TAG rather than being spelled again
		// here: has_shortcode() calls shortcode_exists() first, which is a
		// plain array lookup, so 'Warranty_Cart' never matched the registered
		// 'warranty_cart' and the frontend CSS and JS were never enqueued on a
		// page using it.
		if ( \is_a( $post, 'WP_Post' ) && \has_shortcode( $post->post_content, Shortcode::TAG ) ) {
			return true;
		}

		// The guest warranty lookup, which is a form and a list drawn entirely
		// by the bundle — without this it renders two inputs and a button that
		// does nothing.
		if ( \is_a( $post, 'WP_Post' ) && \has_shortcode( $post->post_content, GuestClaim::TAG ) ) {
			return true;
		}

		// Enqueue on the page chosen in the settings.
		//
		// That page gets the selector appended to its content, so it needs the
		// script and styles even though its content contains no shortcode for
		// has_shortcode() to find.
		$display_page = Shortcode::display_page_id();

		if ( $display_page > 0 && \is_page( $display_page ) ) {
			return true;
		}

		// Enqueue on checkout page
		if ( \is_checkout() ) {
			return true;
		}

		/*
		 * Wherever a warranty is offered alongside a product.
		 *
		 * The offer's buttons post to the cart endpoint, so a product page
		 * carrying one needs the script — without this the buttons render and
		 * do nothing, which is the same failure the selector's own button had
		 * before its route existed.
		 *
		 * The coverage lookup runs only on pages that could show an offer, and
		 * only when the placement setting allows it, so an ordinary product
		 * page on a store with the feature switched off costs nothing.
		 */
		if ( \is_product() && Coverage::shows_on_product() ) {
			/*
			 * The queried object, not `global $product`.
			 *
			 * WooCommerce sets that global from inside the loop, on
			 * `woocommerce_before_main_content` — after `wp_enqueue_scripts` has
			 * already run. Reading it here found null on every product page, so
			 * the offer rendered its buttons and the script that makes them work
			 * was never loaded. The buttons looked fine and did nothing, which is
			 * the same failure the selector's own button had before its route
			 * existed.
			 */
			$queried = \wc_get_product( \get_queried_object_id() );

			if ( $queried instanceof \WC_Product && Coverage::has_offer( $queried ) ) {
				return true;
			}
		}

		if ( \is_cart() && Coverage::shows_in_cart() ) {
			return true;
		}

		/*
		 * The My Account warranties tab.
		 *
		 * It carries the claim form, which is useless without the script that
		 * submits it.
		 *
		 * The query var directly, not `is_wc_endpoint_url()`: that function
		 * consults WooCommerce's own registered endpoints, and this one is
		 * registered with `add_rewrite_endpoint()`, so it answered false and
		 * the tab rendered a form with nothing to submit it. Not `is_page()`
		 * either — that is true across the whole account area and would load
		 * these assets on every tab in it.
		 */
		global $wp_query;

		if ( isset( $wp_query->query_vars[ MyAccount::ENDPOINT ] ) ) {
			return true;
		}

		return false;
	}
}
