<?php
/**
 * Public-facing functionality.
 *
 * Enqueues frontend assets and renders the "Notify Me" form on
 * single product pages.
 *
 * @package Waitlytics
 */

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

/**
 * Class WTLY_Public
 */
class WTLY_Public {

	/**
	 * Whether the inline notify form has already been rendered on this page.
	 *
	 * Prevents duplicate output when more than one display hook fires for
	 * the same product.
	 *
	 * @var bool
	 */
	private $form_rendered = false;

	/**
	 * Initialize public hooks.
	 */
	public function init() {
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ) );

		// Register form display hooks based on settings.
		$settings = wtly_get_settings();
		$position = $settings['notification_position'];

		if ( 'after_add_to_cart' === $position ) {
			add_action( 'woocommerce_after_add_to_cart_form', array( $this, 'maybe_render_form' ), 10 );
		} elseif ( 'after_summary' === $position ) {
			add_action( 'woocommerce_single_product_summary', array( $this, 'maybe_render_form' ), 35 );
		}

		// Out-of-stock fallback: WooCommerce removes the add-to-cart form for
		// out-of-stock products, so woocommerce_after_add_to_cart_form never
		// fires. Hook the summary area (right after the default add-to-cart area
		// at priority 30) to render the form when it was not already shown.
		add_action( 'woocommerce_single_product_summary', array( $this, 'maybe_render_form_out_of_stock' ), 31 );

		// Variable product support — always hook regardless of position.
		add_action( 'woocommerce_after_variations_form', array( $this, 'maybe_render_form_variable' ), 10 );
	}

	/**
	 * Enqueue frontend CSS and JS on single product pages.
	 */
	public function enqueue_assets() {
		if ( ! is_product() ) {
			return;
		}

		wp_enqueue_style(
			'wtly-public',
			WTLY_PLUGIN_URL . 'public/css/wtly-public.css',
			array(),
			WTLY_VERSION
		);

		wp_enqueue_script(
			'wtly-public',
			WTLY_PLUGIN_URL . 'public/js/wtly-public.js',
			array( 'jquery' ),
			WTLY_VERSION,
			true
		);

		wp_localize_script( 'wtly-public', 'wtlyPublicData', array(
			'restUrl' => esc_url_raw( rest_url() ),
			'nonce'   => wp_create_nonce( 'wp_rest' ),
			'i18n'    => array(
				'invalidEmail' => esc_html__( 'Please enter a valid email address.', 'waitlytics' ),
				'error'        => esc_html__( 'Something went wrong. Please try again.', 'waitlytics' ),
			),
		) );
	}

	/**
	 * Conditionally render the notify form for simple products.
	 */
	public function maybe_render_form() {
		global $product;

		if ( ! $product || ! is_a( $product, 'WC_Product' ) ) {
			return;
		}

		// Skip variable products — handled by maybe_render_form_variable.
		if ( $product->is_type( 'variable' ) ) {
			return;
		}

		if ( $this->form_rendered ) {
			return;
		}

		if ( ! $this->should_show_form( $product ) ) {
			return;
		}

		$this->form_rendered = true;
		$this->render_inline_form( $product->get_id(), 0, ! $product->is_in_stock() );
	}

	/**
	 * Render the notify form for out-of-stock simple products.
	 *
	 * WooCommerce removes the add-to-cart form when a product is out of
	 * stock, so woocommerce_after_add_to_cart_form never fires. This summary
	 * hook acts as a fallback for that case only — backorder products still
	 * have the add-to-cart form and are handled by maybe_render_form.
	 */
	public function maybe_render_form_out_of_stock() {
		global $product;

		if ( ! $product || ! is_a( $product, 'WC_Product' ) ) {
			return;
		}

		// Skip variable products — handled by maybe_render_form_variable.
		if ( $product->is_type( 'variable' ) ) {
			return;
		}

		// Only act when the add-to-cart form is absent (out of stock) and the
		// form was not already rendered by the after_add_to_cart_form hook.
		if ( $product->is_in_stock() || $this->form_rendered ) {
			return;
		}

		if ( ! $this->should_show_form( $product ) ) {
			return;
		}

		$this->form_rendered = true;
		$this->render_inline_form( $product->get_id(), 0, true );
	}

	/**
	 * Conditionally render the notify form for variable products.
	 *
	 * For variable products, the form is shown/hidden via JS based
	 * on the selected variation's stock status.
	 */
	public function maybe_render_form_variable() {
		global $product;

		if ( ! $product || ! is_a( $product, 'WC_Product' ) ) {
			return;
		}

		if ( ! $product->is_type( 'variable' ) ) {
			return;
		}

		// Check if form is disabled for this product.
		$disabled = get_post_meta( $product->get_id(), '_wtly_disable_notify_form', true );
		if ( 'yes' === $disabled ) {
			return;
		}

		$settings = wtly_get_settings();
		if ( empty( $settings['enable_notifications'] ) ) {
			return;
		}

		// For variable products, render the form hidden — JS will show/hide.
		$parent_oos = ! $product->is_in_stock();
		$this->render_inline_form( $product->get_id(), 0, $parent_oos, ! $parent_oos );
	}

	/**
	 * Render the inline notify form.
	 *
	 * Public so extension classes (e.g. the Pro shortcode) can reuse the
	 * same form renderer.
	 *
	 * @param int  $product_id   Product ID.
	 * @param int  $variation_id Variation ID.
	 * @param bool $parent_oos   Whether parent product is out of stock.
	 * @param bool $hidden       Whether form should start hidden.
	 */
	public function render_inline_form( $product_id, $variation_id = 0, $parent_oos = false, $hidden = false ) {
		$settings    = wtly_get_settings();
		$subscriber  = new WTLY_Subscriber();
		$sub_count   = $subscriber->count_by_product( $product_id );
		$show_count  = ! empty( $settings['show_subscriber_count'] ) && $sub_count > 0;

		$button_text      = ! empty( $settings['form_button_text'] ) ? $settings['form_button_text'] : __( 'Notify Me', 'waitlytics' );
		$placeholder_text = ! empty( $settings['form_placeholder_text'] ) ? $settings['form_placeholder_text'] : __( 'Enter your email address', 'waitlytics' );

		include WTLY_PLUGIN_DIR . 'templates/forms/notify-me-inline.php';
	}

	/**
	 * Check if the notify form should be displayed for a product.
	 *
	 * Public so extension classes (e.g. the Pro shortcode) can reuse the
	 * same display rules.
	 *
	 * @param WC_Product $product Product object.
	 * @return bool
	 */
	public function should_show_form( $product ) {
		$settings = wtly_get_settings();

		if ( empty( $settings['enable_notifications'] ) ) {
			return false;
		}

		// Check per-product disable.
		$disabled = get_post_meta( $product->get_id(), '_wtly_disable_notify_form', true );
		if ( 'yes' === $disabled ) {
			return false;
		}

		// Show if out of stock or on backorder.
		if ( ! $product->is_in_stock() || $product->is_on_backorder() ) {
			return true;
		}

		return false;
	}

	/**
	 * Force-enqueue assets for form usage outside single product pages.
	 *
	 * Public so extension classes (e.g. the Pro shortcode) can load the
	 * form assets on arbitrary pages.
	 */
	public function enqueue_assets_forced() {
		if ( wp_style_is( 'wtly-public', 'enqueued' ) ) {
			return;
		}

		wp_enqueue_style(
			'wtly-public',
			WTLY_PLUGIN_URL . 'public/css/wtly-public.css',
			array(),
			WTLY_VERSION
		);

		wp_enqueue_script(
			'wtly-public',
			WTLY_PLUGIN_URL . 'public/js/wtly-public.js',
			array( 'jquery' ),
			WTLY_VERSION,
			true
		);

		wp_localize_script( 'wtly-public', 'wtlyPublicData', array(
			'restUrl' => esc_url_raw( rest_url() ),
			'nonce'   => wp_create_nonce( 'wp_rest' ),
			'i18n'    => array(
				'invalidEmail' => esc_html__( 'Please enter a valid email address.', 'waitlytics' ),
				'error'        => esc_html__( 'Something went wrong. Please try again.', 'waitlytics' ),
			),
		) );
	}
}
