<?php

declare(strict_types=1);

namespace ThemeREX\AutoDealer\Integrations\Polylang;

defined( 'ABSPATH' ) || exit;
/**
 * Polylang compatibility layer (ADR-07).
 *
 * Mirrors the field classification in `wpml-config.xml` via Polylang's
 * native filter API:
 *
 *   - `pll_get_post_types`     — CPTs that have translations
 *   - `pll_get_taxonomies`     — taxonomies whose terms have translations
 *   - `pll_copy_post_metas`    — meta keys copied on translation creation
 *   - `pll_translate_post_metas` — meta keys whose value differs per language
 *
 * Plus the same per-language cache and locale-aware price formatting as the
 * WPML integration so cache entries don't bleed and prices read naturally
 * in each locale.
 *
 * @package ThemeREX\AutoDealer
 */
class PolylangIntegration {

	/**
	 * Custom post types that have translations. Mirrors wpml-config.xml.
	 *
	 * @var list<string>
	 */
	private const POST_TYPES = array(
		'trx_ad_listing',
		'trx_ad_dealer',
		'trx_ad_lead',
	);

	/**
	 * Taxonomies with translatable terms. Mirrors wpml-config.xml.
	 *
	 * @var list<string>
	 */
	private const TAXONOMIES = array(
		'trx_ad_make',
		'trx_ad_model',
		'trx_ad_body_style',
		'trx_ad_fuel_type',
		'trx_ad_transmission',
		'trx_ad_drivetrain',
		'trx_ad_color',
		'trx_ad_feature',
		'trx_ad_vehicle_type',
		'trx_ad_condition',
	);

	/**
	 * Meta keys whose VALUE is translatable (different content per language).
	 * Mirrors `<custom-field action="translate">` entries.
	 *
	 * @var list<string>
	 */
	private const TRANSLATE_META = array(
		'_trx_ad_faq',
		'_trx_ad_meta_title',
		'_trx_ad_meta_description',
		'_trx_ad_custom_features',
		'_trx_ad_price_disclaimer',
		'_trx_ad_whatsapp_message',
	);

	/**
	 * Meta keys copied on translation creation (same value across languages).
	 * Mirrors `<custom-field action="copy">` entries.
	 *
	 * @var list<string>
	 */
	private const COPY_META = array(
		'_trx_ad_gallery',
		'_trx_ad_video_url',
		'_trx_ad_video_walkthrough',
		'_trx_ad_view360_url',
		'_trx_ad_brochure_id',
		'_trx_ad_service_history_url',
		'_trx_ad_carfax_url',
		'_trx_ad_features',
		'_trx_ad_interior_material',
		'_trx_ad_towing_capacity',
		'_trx_ad_payload',
		'_trx_ad_qr_code',
	);

	/**
	 * Locale → separator overrides. Same set as WpmlIntegration since the
	 * locales themselves don't change between providers.
	 *
	 * @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( 'pll_get_post_types', array( $this, 'translatablePostTypes' ), 10, 2 );
		add_filter( 'pll_get_taxonomies', array( $this, 'translatableTaxonomies' ), 10, 2 );
		add_filter( 'pll_copy_post_metas', array( $this, 'copyMetas' ) );
		add_filter( 'pll_translate_post_metas', array( $this, 'translateMetas' ) );

		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 );
	}

	/**
	 * Detect if Polylang is active. `pll_current_language()` is the canonical
	 * runtime function; `POLYLANG_VERSION` is the constant the plugin sets.
	 */
	public static function isActive(): bool {
		return function_exists( 'pll_current_language' ) || defined( 'POLYLANG_VERSION' );
	}

	/**
	 * Return the current language slug, or empty string if Polylang isn't
	 * active or hasn't initialised yet.
	 */
	public static function currentLanguage(): string {
		if ( function_exists( 'pll_current_language' ) ) {
			$code = pll_current_language();
			if ( is_string( $code ) && '' !== $code ) {
				return $code;
			}
		}
		return '';
	}

	/**
	 * Add our CPTs to Polylang's translatable list.
	 *
	 * @param array<string,string>|mixed $types  Existing post types (slug → slug).
	 * @param bool                       $hidden Whether hidden types are included.
	 * @return array<string,string>
	 */
	public function translatablePostTypes( $types, bool $hidden ): array {
		unset( $hidden );
		$types = is_array( $types ) ? $types : array();
		foreach ( self::POST_TYPES as $cpt ) {
			$types[ $cpt ] = $cpt;
		}
		return $types;
	}

	/**
	 * Add our taxonomies to Polylang's translatable list.
	 *
	 * @param array<string,string>|mixed $taxonomies Existing taxonomies (slug → slug).
	 * @param bool                       $hidden     Whether hidden taxonomies are included.
	 * @return array<string,string>
	 */
	public function translatableTaxonomies( $taxonomies, bool $hidden ): array {
		unset( $hidden );
		$taxonomies = is_array( $taxonomies ) ? $taxonomies : array();
		foreach ( self::TAXONOMIES as $tax ) {
			$taxonomies[ $tax ] = $tax;
		}
		return $taxonomies;
	}

	/**
	 * @param array<int,string>|mixed $metas
	 * @return array<int,string>
	 */
	public function copyMetas( $metas ): array {
		$metas = is_array( $metas ) ? $metas : array();
		return array_values( array_unique( array_merge( $metas, self::COPY_META ) ) );
	}

	/**
	 * @param array<int,string>|mixed $metas
	 * @return array<int,string>
	 */
	public function translateMetas( $metas ): array {
		$metas = is_array( $metas ) ? $metas : array();
		return array_values( array_unique( array_merge( $metas, self::TRANSLATE_META ) ) );
	}

	/**
	 * @param string $suffix
	 * @param string $name
	 */
	public function languageSuffix( string $suffix, string $name ): string {
		unset( $name );
		$lang = self::currentLanguage();
		if ( '' === $lang ) {
			return $suffix;
		}
		return $suffix . '|pll=' . $lang;
	}

	/**
	 * @param array<string,mixed> $locale
	 * @param float               $price
	 * @return array<string,mixed>
	 */
	public function localizePrice( array $locale, float $price ): array {
		unset( $price );
		$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;
	}

	/**
	 * @param array<string,mixed> $piece
	 * @param int                 $post
	 * @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;
	}
}
