<?php
/**
 * Front-end shortcodes.
 *
 * @package WPDudeProducts
 */

declare(strict_types=1);

namespace WPDude\Products\Frontend;

use WPDude\Products\Products\Product_Meta;

/**
 * Product / images / price / buy shortcodes (source of truth for blocks).
 */
final class Shortcodes {

	/**
	 * Register shortcodes.
	 */
	public function register(): void {
		add_shortcode( 'dude_commerce', array( $this, 'render_product' ) );
		add_shortcode( 'dude_commerce_images', array( $this, 'render_images' ) );
		add_shortcode( 'dude_commerce_price', array( $this, 'render_price' ) );
		add_shortcode( 'dude_commerce_buy', array( $this, 'render_buy' ) );
	}

	/**
	 * [dude_commerce id="123" show_title="yes" button="Buy Now"]
	 *
	 * @param array<string, string>|string $atts Attributes.
	 */
	public function render_product( $atts ): string {
		$atts = shortcode_atts(
			array(
				'id'         => '0',
				'show_title' => 'yes',
				'button'     => '',
			),
			is_array( $atts ) ? $atts : array(),
			'dude_commerce'
		);

		$product_id = absint( $atts['id'] );
		$product    = Product_View::get_product( $product_id );
		if ( ! $product ) {
			return '';
		}

		Assets::mark_needed();

		$show_title = 'no' !== strtolower( (string) $atts['show_title'] );
		$hide_buy   = Return_Pages::should_hide_buy( $product_id );
		$return_ui  = Return_Pages::render_inline_for_product( $product_id );
		$anchor     = Product_View::section_anchor( $product_id );

		ob_start();
		?>
		<div id="<?php echo esc_attr( $anchor ); ?>" class="wpdude-dc-product-section" data-product-id="<?php echo esc_attr( (string) $product_id ); ?>">
			<?php echo $return_ui; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- return UI HTML. ?>
			<div class="wpdude-dc-product<?php echo $hide_buy ? ' wpdude-dc-product--post-purchase' : ''; ?>" data-product-id="<?php echo esc_attr( (string) $product_id ); ?>">
				<?php if ( $show_title ) : ?>
					<h2 class="wpdude-dc-product__title"><?php echo esc_html( get_the_title( $product ) ); ?></h2>
				<?php endif; ?>
				<?php echo $this->render_images( array( 'id' => (string) $product_id ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- shortcode HTML. ?>
				<?php if ( ! $hide_buy ) : ?>
					<?php echo $this->render_price( array( 'id' => (string) $product_id ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- shortcode HTML. ?>
					<?php
					$buy_atts = array(
						'id'     => (string) $product_id,
						'button' => sanitize_text_field( (string) $atts['button'] ),
						'anchor' => 'no',
					);
					echo $this->render_buy( $buy_atts ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- shortcode HTML.
					?>
				<?php endif; ?>
			</div>
		</div>
		<?php
		return (string) ob_get_clean();
	}

	/**
	 * [dude_commerce_images id="123"]
	 *
	 * @param array<string, string>|string $atts Attributes.
	 */
	public function render_images( $atts ): string {
		$atts = shortcode_atts(
			array(
				'id' => '0',
			),
			is_array( $atts ) ? $atts : array(),
			'dude_commerce_images'
		);

		$product_id = absint( $atts['id'] );
		if ( ! Product_View::get_product( $product_id ) ) {
			return '';
		}

		Assets::mark_needed();
		return Product_View::render_images( $product_id );
	}

	/**
	 * [dude_commerce_price id="123"]
	 *
	 * @param array<string, string>|string $atts Attributes.
	 */
	public function render_price( $atts ): string {
		$atts = shortcode_atts(
			array(
				'id' => '0',
			),
			is_array( $atts ) ? $atts : array(),
			'dude_commerce_price'
		);

		$product_id = absint( $atts['id'] );
		if ( ! Product_View::get_product( $product_id ) ) {
			return '';
		}

		if ( Return_Pages::should_hide_buy( $product_id ) ) {
			return '';
		}

		Assets::mark_needed();
		return Product_View::render_price( $product_id );
	}

	/**
	 * [dude_commerce_buy id="123" button="Buy Now"]
	 *
	 * @param array<string, string>|string $atts Attributes.
	 */
	public function render_buy( $atts ): string {
		$atts = shortcode_atts(
			array(
				'id'     => '0',
				'button' => '',
				'anchor' => 'yes',
			),
			is_array( $atts ) ? $atts : array(),
			'dude_commerce_buy'
		);

		$product_id = absint( $atts['id'] );
		$product    = Product_View::get_product( $product_id );
		if ( ! $product ) {
			return '';
		}

		if ( Return_Pages::should_hide_buy( $product_id ) ) {
			return '';
		}

		Assets::mark_needed();

		$type       = Product_Meta::get_type( $product_id );
		$sold_ind   = Product_Meta::is_sold_individually( $product_id );
		$options    = Product_Meta::TYPE_OPTIONS === $type ? Product_Meta::get_options( $product_id ) : array();
		$stock_hint = Product_Meta::TYPE_STANDARD === $type ? Product_Meta::get_stock( $product_id ) : null;
		$button     = trim( (string) $atts['button'] );
		if ( '' === $button ) {
			$button = __( 'Buy Now', 'dude-commerce' );
		}

		$map  = Product_Meta::TYPE_OPTIONS === $type ? Product_View::combination_map( $product_id ) : array();
		$json = wp_json_encode( $map );
		if ( ! is_string( $json ) ) {
			$json = '{}';
		}

		$checkout_nonce = wp_create_nonce( 'wpdude_dc_checkout' );
		$use_anchor     = 'no' !== strtolower( (string) $atts['anchor'] );
		$anchor         = $use_anchor ? Product_View::section_anchor( $product_id ) : '';

		ob_start();
		?>
		<div
			<?php if ( '' !== $anchor ) : ?>
				id="<?php echo esc_attr( $anchor ); ?>"
			<?php endif; ?>
			class="wpdude-dc-buy-now"
			data-product-id="<?php echo esc_attr( (string) $product_id ); ?>"
			data-combinations="<?php echo esc_attr( $json ); ?>"
			data-nonce="<?php echo esc_attr( $checkout_nonce ); ?>"
		>
			<?php if ( ! empty( $options ) ) : ?>
				<?php foreach ( $options as $option ) : ?>
					<p class="wpdude-dc-buy-option">
						<label>
							<strong><?php echo esc_html( $option['name'] ); ?></strong><br />
							<select class="wpdude-dc-option-select" name="<?php echo esc_attr( $option['name'] ); ?>" required>
								<option value=""><?php echo esc_html__( 'Choose…', 'dude-commerce' ); ?></option>
								<?php foreach ( $option['values'] as $entry ) : ?>
									<option value="<?php echo esc_attr( $entry['value'] ); ?>"><?php echo esc_html( $entry['value'] ); ?></option>
								<?php endforeach; ?>
							</select>
						</label>
					</p>
				<?php endforeach; ?>
			<?php endif; ?>

			<?php if ( ! $sold_ind ) : ?>
				<p class="wpdude-dc-buy-qty">
					<label>
						<strong><?php echo esc_html__( 'Quantity', 'dude-commerce' ); ?></strong><br />
						<input type="number" class="wpdude-dc-qty" name="qty" value="1" min="1" step="1" <?php echo null !== $stock_hint ? 'max="' . esc_attr( (string) max( 1, $stock_hint ) ) . '"' : ''; ?> />
					</label>
				</p>
			<?php else : ?>
				<input type="hidden" class="wpdude-dc-qty" value="1" />
			<?php endif; ?>

			<p>
				<button type="button" class="button wpdude-dc-buy-button"><?php echo esc_html( $button ); ?></button>
			</p>
			<p class="wpdude-dc-buy-message" hidden></p>
		</div>
		<?php
		return (string) ob_get_clean();
	}
}
