<?php

declare(strict_types=1);

namespace ThemeREX\AutoDealer\Integrations\WPML;

defined( 'ABSPATH' ) || exit;
/**
 * WPML compatibility layer (ADR-07).
 *
 * Field classification (translate / copy / ignore) is declared in
 * `wpml-config.xml` at the plugin root — WPML reads that file automatically
 * on plugin activation and applies the rules. This class handles the
 * runtime-only concerns the config file can't express:
 *
 *   - cache keys must be per-language (otherwise `?make=Toyota` returns
 *     Spanish counts to English visitors)
 *   - price formatting separators flip per locale
 *   - schema.org pieces declare `inLanguage` matching the current request
 *
 * @package ThemeREX\AutoDealer
 */
class WpmlIntegration {

	/**
	 * Locales → separator overrides. Curated list of common locales where
	 * decimal/thousands separators differ from the en_US defaults. Locales
	 * not in the map fall through to whatever the plugin settings say.
	 *
	 * @var array<string, array{decimal_sep: string, thousands_sep: string}>
	 */
	private const LOCALE_SEPARATORS = array(
		'de'    => array(
			'decimal_sep'   => ',',
			'thousands_sep' => '.',
		),
		'fr'    => array(
			'decimal_sep'   => ',',
			'thousands_sep' => ' ',
		),
		'es'    => array(
			'decimal_sep'   => ',',
			'thousands_sep' => '.',
		),
		'it'    => array(
			'decimal_sep'   => ',',
			'thousands_sep' => '.',
		),
		'nl'    => array(
			'decimal_sep'   => ',',
			'thousands_sep' => '.',
		),
		'pt-br' => array(
			'decimal_sep'   => ',',
			'thousands_sep' => '.',
		),
		'pt'    => array(
			'decimal_sep'   => ',',
			'thousands_sep' => '.',
		),
		'ru'    => array(
			'decimal_sep'   => ',',
			'thousands_sep' => ' ',
		),
		'pl'    => array(
			'decimal_sep'   => ',',
			'thousands_sep' => ' ',
		),
	);

	public function register(): void {
		if ( ! self::isActive() ) {
			return;
		}

		add_filter( 'trx_ad_cache_key_suffix', array( $this, 'languageSuffix' ), 10, 2 );
		add_filter( 'trx_ad_format_price_locale', array( $this, 'localizePrice' ), 10, 2 );
		add_filter( 'trx_ad_schema_car_piece', array( $this, 'addInLanguage' ), 10, 2 );
		add_filter( 'trx_ad_schema_autodealer_piece', array( $this, 'addInLanguage' ), 10, 2 );
		add_action( 'trx_ad_register_modules', array( $this, 'registerSitemapHreflang' ) );
	}

	/**
	 * Detect if WPML is active. `ICL_LANGUAGE_CODE` is defined by WPML
	 * core on every request after `plugins_loaded`; `SitePress` is its
	 * main class. Either signal is sufficient.
	 */
	public static function isActive(): bool {
		return defined( 'ICL_LANGUAGE_CODE' ) || class_exists( 'SitePress', false );
	}

	/**
	 * Return the current request's WPML language code. Falls back to
	 * the configured default language when the constant isn't set yet.
	 */
	public static function currentLanguage(): string {
		if ( defined( 'ICL_LANGUAGE_CODE' ) ) {
			$code = (string) ICL_LANGUAGE_CODE;
			if ( '' !== $code ) {
				return $code;
			}
		}

		$filtered = apply_filters( 'wpml_current_language', null );
		if ( is_string( $filtered ) && '' !== $filtered ) {
			return $filtered;
		}

		return '';
	}

	/**
	 * Append the current language code to the aggregation cache key.
	 *
	 * @param string $suffix Existing suffix (chained from other filters).
	 * @param string $name   Cache name (unused but available for finer-grained scoping).
	 */
	public function languageSuffix( string $suffix, string $name ): string {
		$lang = self::currentLanguage();
		if ( '' === $lang ) {
			return $suffix;
		}
		return $suffix . '|wpml=' . $lang;
	}

	/**
	 * Override decimal/thousands separators based on the current language.
	 *
	 * @param array<string,mixed> $locale Existing locale config.
	 * @param float               $price  The price (unused but in signature).
	 * @return array<string,mixed>
	 */
	public function localizePrice( array $locale, float $price ): array {
		$lang = strtolower( self::currentLanguage() );
		if ( '' === $lang ) {
			return $locale;
		}

		if ( isset( self::LOCALE_SEPARATORS[ $lang ] ) ) {
			$locale['decimal_sep']   = self::LOCALE_SEPARATORS[ $lang ]['decimal_sep'];
			$locale['thousands_sep'] = self::LOCALE_SEPARATORS[ $lang ]['thousands_sep'];
		}

		return $locale;
	}

	/**
	 * Add the `inLanguage` property to schema pieces so search engines see
	 * the correct language for each translation. Without this, all language
	 * versions emit identical schema and Google can pick the wrong one for
	 * a given locale's results.
	 *
	 * @param array<string,mixed> $piece Schema piece.
	 * @param int                 $post  Post ID.
	 * @return array<string,mixed>
	 */
	public function addInLanguage( array $piece, int $post ): array {
		unset( $post );

		$lang = self::currentLanguage();
		if ( '' === $lang ) {
			return $piece;
		}

		if ( ! isset( $piece['inLanguage'] ) ) {
			$piece['inLanguage'] = $lang;
		}

		return $piece;
	}

	/**
	 * Hint registration entry point — sites/themes wanting to add hreflang
	 * tags or sitemap variants per language can hook off this action.
	 *
	 * Free-tier plugin doesn't ship a multi-language sitemap; that's a
	 * Pro-tier concern (Pro/Sitemap module would consume `wpml_active_languages`).
	 */
	public function registerSitemapHreflang(): void {
		do_action( 'trx_ad_wpml_ready', self::currentLanguage() );
	}
}
