<?php
/**
 * Shortcode service provider.
 *
 * @package Affilun\Presentation\Shortcode
 */

declare(strict_types=1);

namespace Affilun\Presentation\Shortcode;

use Affilun\Bootstrap\HookRegistrar;
use Affilun\Bootstrap\AmazonDiscountServiceProvider;
use Affilun\Bootstrap\ServiceProvider;
use Affilun\Bootstrap\ServiceProviderRegistry;
use Affilun\Presentation\Block\BlockServiceProvider;
use Affilun\Presentation\Block\ProductCardBlockRenderer;
use LogicException;

/**
 * Registers Classic Editor shortcode bridges for product cards/grids.
 */
final class ShortcodeServiceProvider implements ServiceProvider {

	/**
	 * Registry binding for the shortcode renderer.
	 */
	public const BINDING_PRODUCT_SHORTCODE_RENDERER = 'affilun.shortcode.product_renderer';

	/**
	 * Resolved renderer.
	 */
	private ?ProductShortcodeRenderer $renderer = null;

	/**
	 * Optional Amazon discount shortcode renderer.
	 */
	private ?AmazonDiscountShortcodeRenderer $amazonDiscountRenderer = null;

	/**
	 * Register shortcode renderer.
	 *
	 * @param ServiceProviderRegistry $registry Registry.
	 */
	public function register( ServiceProviderRegistry $registry ): void {
		$cardRenderer = $this->resolveCardRenderer( $registry );

		$renderer = new ProductShortcodeRenderer(
			static fn ( array $attributes ): string => $cardRenderer->render( $attributes )
		);

		$this->renderer = $renderer;
		$registry->bind( self::BINDING_PRODUCT_SHORTCODE_RENDERER, $renderer );

		$key = AmazonDiscountServiceProvider::BINDING_SHORTCODE_RENDERER;
		if ( $registry->has( $key ) ) {
			$value = $registry->get( $key );
			if ( $value instanceof AmazonDiscountShortcodeRenderer ) {
				$this->amazonDiscountRenderer = $value;
			}
		}
	}

	/**
	 * Wire shortcode registration onto init.
	 *
	 * @param HookRegistrar $hooks Hooks.
	 */
	public function boot( HookRegistrar $hooks ): void {
		$hooks->addAction( 'init', array( $this, 'onInit' ) );
	}

	/**
	 * Register shortcodes with WordPress.
	 */
	public function onInit(): void {
		if ( $this->renderer === null || ! function_exists( 'add_shortcode' ) ) {
			return;
		}

		add_shortcode( 'affilun_product_card', array( $this->renderer, 'renderCardShortcode' ) );
		if ( $this->amazonDiscountRenderer !== null ) {
			add_shortcode(
				'affilun_amazon_discounts',
				array( $this->amazonDiscountRenderer, 'renderShortcode' )
			);
		}
	}

	/**
	 * Resolve card block renderer.
	 *
	 * @param ServiceProviderRegistry $registry Registry.
	 *
	 * @throws LogicException When the renderer binding is missing or invalid.
	 */
	private function resolveCardRenderer( ServiceProviderRegistry $registry ): ProductCardBlockRenderer {
		$key = BlockServiceProvider::BINDING_PRODUCT_CARD_BLOCK_RENDERER;
		if ( ! $registry->has( $key ) ) {
			throw new LogicException( 'ShortcodeServiceProvider requires BlockServiceProvider card renderer.' );
		}
		$renderer = $registry->get( $key );
		if ( ! $renderer instanceof ProductCardBlockRenderer ) {
			throw new LogicException( 'ShortcodeServiceProvider expected ProductCardBlockRenderer.' );
		}
		return $renderer;
	}
}
