<?php
/**
 * Donor-facing country selector shortcode and asset registration.
 *
 * @since   1.0.0
 * @package DonationRouter
 */

declare( strict_types=1 );
namespace DonationRouter;

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

/**
 * Registers the [ador_country_selector] shortcode and enqueues frontend assets.
 *
 * The shortcode renders hidden GiveWP forms wrapped in routing containers plus
 * a modal overlay that lets donors explicitly choose their country. The
 * JavaScript module then reveals the matching form and records the choice in
 * sessionStorage so subsequent page loads in the same session skip the modal.
 *
 * Shortcode attributes:
 *   - trigger            "auto"|"button" — how the modal opens. Default: "auto".
 *   - default_country    ISO code — skip modal if matched. Default: "".
 *   - show_descriptions  "yes"|"no". Default: "yes".
 *   - heading            Modal heading text. Default: localised string.
 *
 * @since 1.0.0
 */
class Country_Selector {

	use Template_Loader;

	/**
	 * Shortcode tag.
	 *
	 * @since 1.0.0
	 *
	 * @var string
	 */
	public const SHORTCODE = 'ador_country_selector';

	/**
	 * Script/style handle for the frontend selector.
	 *
	 * @since 1.0.0
	 *
	 * @var string
	 */
	public const HANDLE = 'ador-country-selector';

	/**
	 * Routing data source.
	 *
	 * @since 1.0.0
	 *
	 * @var Country_Routing_Repository_Interface
	 */
	private Country_Routing_Repository_Interface $routing_repo;

	/**
	 * Geolocation hint resolver.
	 *
	 * @since 1.0.0
	 *
	 * @var Geolocation_Hint
	 */
	private Geolocation_Hint $geo;

	/**
	 * Initialise with required dependencies.
	 *
	 * @since 1.0.0
	 *
	 * @param Country_Routing_Repository_Interface $routing_repo  Active routing rules source.
	 * @param Geolocation_Hint                     $geo           Geolocation hint resolver.
	 */
	public function __construct(
		Country_Routing_Repository_Interface $routing_repo,
		Geolocation_Hint $geo
	) {
		$this->routing_repo = $routing_repo;
		$this->geo          = $geo;
	}

	/**
	 * Register WordPress hooks.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public function register_hooks(): void {
		add_shortcode( self::SHORTCODE, array( $this, 'render_shortcode' ) );
		add_action( 'wp_enqueue_scripts', array( $this, 'register_assets' ) );
	}

	/**
	 * Register (but do not enqueue) frontend assets.
	 *
	 * Assets are enqueued on demand inside render_shortcode() so they only load
	 * on pages that use the shortcode.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public function register_assets(): void {
		$asset_file = ADOR_PATH . 'build/country-selector.asset.php';
		$asset      = file_exists( $asset_file )
			? require $asset_file
			: array(
				'dependencies' => array(),
				'version'      => ADOR_VERSION,
			);

		wp_register_style(
			self::HANDLE,
			ADOR_URL . 'build/country-selector.css',
			array(),
			$asset['version']
		);

		wp_register_script(
			self::HANDLE,
			ADOR_URL . 'build/country-selector.js',
			$asset['dependencies'],
			$asset['version'],
			array(
				'in_footer' => true,
				'strategy'  => 'defer',
			)
		);
	}

	/**
	 * Render the [ador_country_selector] shortcode.
	 *
	 * @since 1.0.0
	 *
	 * @param  array<string,mixed>|string $attrs  Shortcode attributes (or empty string).
	 *
	 * @return string  HTML output.
	 */
	public function render_shortcode( $attrs ): string {
		$attrs = shortcode_atts(
			array(
				'trigger'           => 'auto',
				'default_country'   => '',
				'show_descriptions' => 'yes',
				'heading'           => __( 'Where would you like your donation to be processed?', 'alamin-donation-router' ),
			),
			is_array( $attrs ) ? $attrs : array(),
			self::SHORTCODE
		);

		$trigger           = in_array( (string) $attrs['trigger'], array( 'auto', 'button' ), true ) ? (string) $attrs['trigger'] : 'auto';
		$default_country   = strtoupper( sanitize_key( (string) $attrs['default_country'] ) );
		$show_descriptions = 'yes' === (string) $attrs['show_descriptions'];
		$heading           = wp_kses_post( (string) $attrs['heading'] );

		$routings = $this->routing_repo->find_all_active();

		if ( empty( $routings ) ) {
			return '';
		}

		wp_enqueue_style( self::HANDLE );
		wp_enqueue_script( self::HANDLE );

		$geo_hint = $this->geo->get_country_hint();

		$routing_data = $this->build_routing_data( $routings, $show_descriptions );

		ob_start();
		$this->render_wrapper( $trigger, $default_country, $heading, $routings, $routing_data, $geo_hint );
		return (string) ob_get_clean();
	}

	/**
	 * Build the JSON-serialisable routing data array for the JavaScript module.
	 *
	 * Credentials and internal IDs are omitted — only display data and routing
	 * keys are included.
	 *
	 * @since 1.0.0
	 *
	 * @param  Country_Routing[] $routings          Active routing rules.
	 * @param  bool              $show_descriptions  Whether to include descriptions.
	 *
	 * @return array<int,array<string,mixed>>
	 */
	private function build_routing_data( array $routings, bool $show_descriptions ): array {
		$data = array();
		foreach ( $routings as $routing ) {
			$entry = array(
				'countryCode' => $routing->country_code,
				'formId'      => $routing->form_id,
				'label'       => $routing->display_label,
				'sortOrder'   => $routing->sort_order,
			);

			if ( $show_descriptions && null !== $routing->display_description ) {
				$entry['description'] = $routing->display_description;
			}

			$data[] = $entry;
		}

		return $data;
	}

	/**
	 * Output the full shortcode HTML.
	 *
	 * @since 1.0.0
	 *
	 * @param  string                         $trigger         "auto" or "button".
	 * @param  string                         $default_country  Pre-selected ISO code (may be empty).
	 * @param  string                         $heading          Modal heading.
	 * @param  Country_Routing[]              $routings         Active routing rules.
	 * @param  array<int,array<string,mixed>> $routing_data  JSON data for JS.
	 * @param  string|null                    $geo_hint         Suggested country code from geolocation.
	 *
	 * @return void
	 */
	private function render_wrapper(
		string $trigger,
		string $default_country,
		string $heading,
		array $routings,
		array $routing_data,
		?string $geo_hint
	): void {
		$instance_id = 'ador-selector-' . wp_unique_id();
		$this->render_template(
			'frontend/country-selector.php',
			compact( 'instance_id', 'trigger', 'default_country', 'heading', 'routings', 'routing_data', 'geo_hint' )
		);
	}
}
