<?php
namespace TeknoTok\AiTranslator\Frontend;

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

/**
 * Controller to handle frontend language switcher rendering and assets.
 */
class SwitcherController {
	/**
	 * Preset switcher designs customers can start from.
	 *
	 * @return array
	 */
	public static function get_design_presets() {
		return array(
			'glass'   => array(
				'label'            => __( 'Modern Glass', 'teknotok-ai-translator' ),
				'background_color' => '#f8fafc',
				'text_color'       => '#0f172a',
				'border_color'     => '#cbd5e1',
				'accent_color'     => '#2563eb',
				'opacity'          => 94,
				'shape'            => 'pill',
				'border_width'     => 1,
				'show_flags'       => '1',
			),
			'water'   => array(
				'label'            => __( 'Fresh Water', 'teknotok-ai-translator' ),
				'background_color' => '#f0fdfa',
				'text_color'       => '#134e4a',
				'border_color'     => '#5eead4',
				'accent_color'     => '#0f766e',
				'opacity'          => 92,
				'shape'            => 'rounded',
				'border_width'     => 1,
				'show_flags'       => '1',
			),
			'clean'   => array(
				'label'            => __( 'Clean Light', 'teknotok-ai-translator' ),
				'background_color' => '#ffffff',
				'text_color'       => '#111827',
				'border_color'     => '#e5e7eb',
				'accent_color'     => '#374151',
				'opacity'          => 100,
				'shape'            => 'rounded',
				'border_width'     => 1,
				'show_flags'       => '1',
			),
			'dark'    => array(
				'label'            => __( 'Midnight', 'teknotok-ai-translator' ),
				'background_color' => '#111827',
				'text_color'       => '#f9fafb',
				'border_color'     => '#475569',
				'accent_color'     => '#f59e0b',
				'opacity'          => 96,
				'shape'            => 'pill',
				'border_width'     => 1,
				'show_flags'       => '1',
			),
		);
	}

	/**
	 * Sanitize switcher design settings.
	 *
	 * @param array $settings Raw settings.
	 * @return array
	 */
	public static function sanitize_design_settings( $settings ) {
		$presets = self::get_design_presets();
		$preset  = isset( $settings['switcher_design_preset'] ) ? sanitize_key( $settings['switcher_design_preset'] ) : 'glass';
		if ( ! isset( $presets[ $preset ] ) ) {
			$preset = 'glass';
		}

		$base = $presets[ $preset ];
		$shape = isset( $settings['switcher_shape'] ) ? sanitize_key( $settings['switcher_shape'] ) : $base['shape'];
		if ( ! in_array( $shape, array( 'pill', 'rounded', 'square' ), true ) ) {
			$shape = $base['shape'];
		}

		return array(
			'switcher_design_preset' => $preset,
			'switcher_show_flags'    => array_key_exists( 'switcher_show_flags', $settings ) ? ( ! empty( $settings['switcher_show_flags'] ) ? '1' : '0' ) : $base['show_flags'],
			'switcher_opacity'       => max( 40, min( 100, (int) ( $settings['switcher_opacity'] ?? $base['opacity'] ) ) ),
			'switcher_text_color'    => self::sanitize_hex_color( $settings['switcher_text_color'] ?? $base['text_color'], $base['text_color'] ),
			'switcher_bg_color'      => self::sanitize_hex_color( $settings['switcher_bg_color'] ?? $base['background_color'], $base['background_color'] ),
			'switcher_border_color'  => self::sanitize_hex_color( $settings['switcher_border_color'] ?? $base['border_color'], $base['border_color'] ),
			'switcher_accent_color'  => self::sanitize_hex_color( $settings['switcher_accent_color'] ?? $base['accent_color'], $base['accent_color'] ),
			'switcher_shape'         => $shape,
			'switcher_border_width'  => max( 0, min( 4, (int) ( $settings['switcher_border_width'] ?? $base['border_width'] ) ) ),
		);
	}

	/**
	 * Constructor. Registers shortcode and output hooks.
	 */
	public function __construct() {
		add_shortcode( 'teknotok_language_switcher', array( $this, 'render_switcher_shortcode' ) );
		add_action( 'wp_footer', array( $this, 'render_floating_switcher' ) );
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ) );
	}

	/**
	 * Enqueue switcher styles and scripts.
	 *
	 * @return void
	 */
	public function enqueue_assets() {
		wp_enqueue_style( 'teknotok-ait-switcher', TEKNOTOK_AIT_URL . 'assets/css/switcher.css', array(), TEKNOTOK_AIT_VERSION );
		wp_enqueue_script( 'teknotok-ait-switcher', TEKNOTOK_AIT_URL . 'assets/js/switcher.js', array( 'jquery' ), TEKNOTOK_AIT_VERSION, true );

		$settings = get_option( 'teknotok_ait_settings', array() );
		$source = $settings['source_language'] ?? 'en';
		$targets = \TeknoTok\AiTranslator\Plugin::normalize_target_languages( $settings['target_languages'] ?? array(), $source );
		$active_lang = \TeknoTok\AiTranslator\Plugin::get_active_language();
		$all_langs = array_merge( array( $source ), $targets );

		$lang_urls = array();
		foreach ( $all_langs as $lang ) {
			$lang_urls[ $lang ] = \TeknoTok\AiTranslator\Frontend\UrlManager::get_clean_url_for_language( $lang );
		}

		wp_localize_script(
			'teknotok-ait-switcher',
			'teknotokAitSwitcher',
			array(
				'sourceLanguage'       => $source,
				'activeLanguage'       => $active_lang,
				'urls'                 => $lang_urls,
				'checkoutTranslations' => $this->get_checkout_display_translations(),
			)
		);
	}

	/**
	 * Build no-token checkout/cart replacement strings from translation memory.
	 *
	 * @return array Source text to translated text map.
	 */
	private function get_checkout_display_translations() {
		$active_lang = \TeknoTok\AiTranslator\Plugin::get_active_language();
		$settings    = get_option( 'teknotok_ait_settings', array() );
		$source_lang = $settings['source_language'] ?? 'en';

		if ( $active_lang === $source_lang ) {
			return array();
		}

		$translations = array();

		$this->add_classic_checkout_field_translations( $translations, $active_lang );
		$this->add_blocks_checkout_field_translations( $translations, $active_lang );
		$this->add_payment_gateway_translations( $translations, $active_lang );
		$this->add_shipping_display_translations( $translations, $active_lang );

		if ( function_exists( 'WC' ) && WC() && isset( WC()->cart ) && WC()->cart ) {
			foreach ( WC()->cart->get_cart() as $cart_item ) {
				if ( empty( $cart_item['data'] ) || ! is_object( $cart_item['data'] ) ) {
					continue;
				}

				$product    = $cart_item['data'];
				$product_id = method_exists( $product, 'get_id' ) ? (int) $product->get_id() : 0;
				if ( method_exists( $product, 'get_parent_id' ) ) {
					$parent_id = (int) $product->get_parent_id();
					if ( $parent_id > 0 ) {
						$product_id = $parent_id;
					}
				}

				if ( $product_id > 0 ) {
					$this->add_checkout_display_translation( $translations, get_post_field( 'post_title', $product_id ), $active_lang );
					$this->add_checkout_display_translation( $translations, get_post_field( 'post_excerpt', $product_id ), $active_lang );
				}

				if ( method_exists( $product, 'get_name' ) ) {
					$this->add_checkout_display_translation( $translations, $product->get_name(), $active_lang );
				}
			}
		}

		return $translations;
	}

	/**
	 * Add WooCommerce payment gateway display text replacements.
	 *
	 * @param array  $translations Replacement map.
	 * @param string $active_lang  Target language.
	 * @return void
	 */
	private function add_payment_gateway_translations( &$translations, $active_lang ) {
		if ( ! function_exists( 'WC' ) || ! WC() || ! WC()->payment_gateways() ) {
			return;
		}

		$gateways = WC()->payment_gateways()->payment_gateways();
		if ( empty( $gateways ) || ! is_array( $gateways ) ) {
			return;
		}

		foreach ( $gateways as $gateway ) {
			if ( ! is_object( $gateway ) ) {
				continue;
			}

			foreach ( array( 'title', 'description', 'method_title', 'method_description' ) as $property ) {
				if ( isset( $gateway->{$property} ) && is_scalar( $gateway->{$property} ) ) {
					$this->add_checkout_display_translation( $translations, $gateway->{$property}, $active_lang );
				}
			}

			if ( method_exists( $gateway, 'get_title' ) ) {
				$this->add_checkout_display_translation( $translations, $gateway->get_title(), $active_lang );
			}
			if ( method_exists( $gateway, 'get_description' ) ) {
				$this->add_checkout_display_translation( $translations, $gateway->get_description(), $active_lang );
			}
		}
	}

	/**
	 * Add WooCommerce shipping and cart display replacements.
	 *
	 * @param array  $translations Replacement map.
	 * @param string $active_lang  Target language.
	 * @return void
	 */
	private function add_shipping_display_translations( &$translations, $active_lang ) {
		foreach ( $this->get_shipping_display_source_strings() as $source_text ) {
			$this->add_checkout_display_translation( $translations, $source_text, $active_lang );
		}
	}

	/**
	 * Collect WooCommerce shipping and cart labels that may render through block JavaScript.
	 *
	 * @return array Shipping and cart source-language strings.
	 */
	private function get_shipping_display_source_strings() {
		$strings = array(
			'Shipping',
			'Free shipping',
			'Flat rate',
			'Local pickup',
			'Subtotal',
			'Total',
			'Cart totals',
			'Estimated total',
			'Proceed to checkout',
			'Apply coupon',
		);

		if ( ! function_exists( 'WC' ) || ! WC() ) {
			return $strings;
		}

		if ( WC()->shipping() && method_exists( WC()->shipping(), 'get_shipping_methods' ) ) {
			$shipping_methods = WC()->shipping()->get_shipping_methods();
			if ( is_array( $shipping_methods ) ) {
				foreach ( $shipping_methods as $method ) {
					$strings = array_merge( $strings, $this->get_shipping_method_strings( $method ) );
				}
			}
		}

		if ( class_exists( '\WC_Shipping_Zones' ) ) {
			$zones = \WC_Shipping_Zones::get_zones();
			if ( is_array( $zones ) ) {
				foreach ( $zones as $zone ) {
					if ( empty( $zone['shipping_methods'] ) || ! is_array( $zone['shipping_methods'] ) ) {
						continue;
					}

					foreach ( $zone['shipping_methods'] as $method ) {
						$strings = array_merge( $strings, $this->get_shipping_method_strings( $method ) );
					}
				}
			}

			$default_zone = \WC_Shipping_Zones::get_zone_by( 'zone_id', 0 );
			if ( is_object( $default_zone ) && method_exists( $default_zone, 'get_shipping_methods' ) ) {
				$default_methods = $default_zone->get_shipping_methods();
				if ( is_array( $default_methods ) ) {
					foreach ( $default_methods as $method ) {
						$strings = array_merge( $strings, $this->get_shipping_method_strings( $method ) );
					}
				}
			}
		}

		return array_values( array_filter( array_unique( array_map( 'trim', $strings ) ) ) );
	}

	/**
	 * Collect display labels from one WooCommerce shipping method object.
	 *
	 * @param object $method Shipping method object.
	 * @return array Method source-language strings.
	 */
	private function get_shipping_method_strings( $method ) {
		if ( ! is_object( $method ) ) {
			return array();
		}

		$strings = array();
		foreach ( array( 'title', 'method_title', 'method_description' ) as $property ) {
			if ( isset( $method->{$property} ) && is_scalar( $method->{$property} ) ) {
				$strings[] = wp_strip_all_tags( (string) $method->{$property} );
			}
		}

		foreach ( array( 'get_title', 'get_method_title', 'get_method_description' ) as $method_name ) {
			if ( method_exists( $method, $method_name ) ) {
				$value = $method->{$method_name}();
				if ( is_scalar( $value ) ) {
					$strings[] = wp_strip_all_tags( (string) $value );
				}
			}
		}

		return $strings;
	}

	/**
	 * Add classic WooCommerce checkout field text replacements.
	 *
	 * @param array  $translations Replacement map.
	 * @param string $active_lang  Target language.
	 * @return void
	 */
	private function add_classic_checkout_field_translations( &$translations, $active_lang ) {
		if ( ! function_exists( 'WC' ) || ! WC() || ! function_exists( 'is_checkout' ) || ! is_checkout() ) {
			return;
		}

		if ( ! function_exists( 'WC' ) || ! WC()->checkout() ) {
			return;
		}

		$fields = WC()->checkout()->get_checkout_fields();
		if ( empty( $fields ) || ! is_array( $fields ) ) {
			return;
		}

		foreach ( $fields as $field_group ) {
			if ( ! is_array( $field_group ) ) {
				continue;
			}

			foreach ( $field_group as $field ) {
				if ( ! is_array( $field ) ) {
					continue;
				}

				foreach ( array( 'label', 'placeholder', 'description' ) as $text_key ) {
					if ( isset( $field[ $text_key ] ) ) {
						$this->add_checkout_display_translation( $translations, $field[ $text_key ], $active_lang );
					}
				}

				if ( ! empty( $field['options'] ) && is_array( $field['options'] ) ) {
					foreach ( $field['options'] as $option_label ) {
						$this->add_checkout_display_translation( $translations, $option_label, $active_lang );
					}
				}
			}
		}
	}

	/**
	 * Add WooCommerce Blocks additional checkout field text replacements.
	 *
	 * @param array  $translations Replacement map.
	 * @param string $active_lang  Target language.
	 * @return void
	 */
	private function add_blocks_checkout_field_translations( &$translations, $active_lang ) {
		if ( ! class_exists( '\Automattic\WooCommerce\Blocks\Package' ) || ! class_exists( '\Automattic\WooCommerce\Blocks\Domain\Services\CheckoutFields' ) ) {
			return;
		}

		try {
			$controller = \Automattic\WooCommerce\Blocks\Package::container()->get( \Automattic\WooCommerce\Blocks\Domain\Services\CheckoutFields::class );
		} catch ( \Throwable $e ) {
			return;
		}

		if ( ! is_object( $controller ) || ! method_exists( $controller, 'get_additional_fields' ) ) {
			return;
		}

		$fields = $controller->get_additional_fields();
		if ( empty( $fields ) || ! is_array( $fields ) ) {
			return;
		}

		foreach ( $fields as $field ) {
			if ( ! is_array( $field ) ) {
				continue;
			}

			foreach ( array( 'label', 'optionalLabel' ) as $text_key ) {
				if ( isset( $field[ $text_key ] ) ) {
					$this->add_checkout_display_translation( $translations, $field[ $text_key ], $active_lang );
				}
			}

			if ( ! empty( $field['options'] ) && is_array( $field['options'] ) ) {
				foreach ( $field['options'] as $option ) {
					if ( is_array( $option ) && isset( $option['label'] ) ) {
						$this->add_checkout_display_translation( $translations, $option['label'], $active_lang );
					}
				}
			}
		}
	}

	/**
	 * Add one no-token checkout display replacement from translation memory.
	 *
	 * @param array  $translations Replacement map.
	 * @param string $source_text  Source text.
	 * @param string $active_lang  Target language.
	 * @return void
	 */
	private function add_checkout_display_translation( &$translations, $source_text, $active_lang ) {
		$source_text = trim( wp_strip_all_tags( html_entity_decode( (string) $source_text, ENT_QUOTES, 'UTF-8' ) ) );
		if ( '' === $source_text ) {
			return;
		}

		$translated = $this->get_checkout_memory_translation( $source_text, $active_lang );
		if ( false === $translated || '' === trim( (string) $translated ) ) {
			return;
		}

		$translations[ $source_text ] = html_entity_decode( (string) $translated, ENT_QUOTES, 'UTF-8' );
	}

	/**
	 * Read checkout display text from translation memory using common text variants.
	 *
	 * @param string $source_text Source text.
	 * @param string $active_lang Target language.
	 * @return string|false Translated text when cached.
	 */
	private function get_checkout_memory_translation( $source_text, $active_lang ) {
		$variants = array(
			(string) $source_text,
			html_entity_decode( (string) $source_text, ENT_QUOTES, 'UTF-8' ),
			wp_strip_all_tags( html_entity_decode( (string) $source_text, ENT_QUOTES, 'UTF-8' ) ),
		);

		foreach ( array_unique( $variants ) as $variant ) {
			$variant = trim( $variant );
			if ( '' === $variant ) {
				continue;
			}

			$cached = \TeknoTok\AiTranslator\Database\MemoryRepository::get_translation( $variant, $active_lang );
			if ( false !== $cached ) {
				return $cached;
			}
		}

		return false;
	}

	/**
	 * Output markup for the language switcher list.
	 *
	 * @return string HTML output.
	 */
	public function render_switcher_html() {
		$settings = get_option( 'teknotok_ait_settings', array() );
		$source = $settings['source_language'] ?? 'en';
		$targets = $settings['target_languages'] ?? array();
		$position = $settings['switcher_position'] ?? 'floating-bottom-right';
		$design = self::sanitize_design_settings( $settings );

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

		$languages = \TeknoTok\AiTranslator\Plugin::get_supported_languages();
		$switcher_languages = $this->get_switcher_language_names( $languages );
		$targets = $this->sort_switcher_targets( $targets, $source, $languages );

		$active_lang = \TeknoTok\AiTranslator\Plugin::get_active_language();
		$total_languages = count( $targets ) + 1;
		$show_referral = $this->should_show_referral( $settings );
		$direction = $this->is_rtl_language( $active_lang ) ? 'rtl' : 'ltr';
		$container_classes = array(
			'teknotok-ait-switcher-container',
			'teknotok-ait-position-' . sanitize_html_class( $position ),
			'teknotok-ait-design-' . sanitize_html_class( $design['switcher_design_preset'] ),
			'teknotok-ait-shape-' . sanitize_html_class( $design['switcher_shape'] ),
			'notranslate',
		);
		if ( '0' === $design['switcher_show_flags'] ) {
			$container_classes[] = 'teknotok-ait-no-flags';
		}
		if ( 'rtl' === $direction ) {
			$container_classes[] = 'teknotok-ait-rtl';
		}

		ob_start();
		?>
		<div class="<?php echo esc_attr( implode( ' ', $container_classes ) ); ?>" style="<?php echo esc_attr( $this->get_design_inline_style( $design ) ); ?>" translate="no" dir="<?php echo esc_attr( $direction ); ?>">
			<div class="teknotok-ait-selected-lang" role="button" tabindex="0" aria-haspopup="listbox" aria-expanded="false">
				<img src="<?php echo esc_url( self::get_flag_url( $active_lang ) ); ?>" class="teknotok-ait-flag" alt="<?php echo esc_attr( $active_lang ); ?>" />
				<span class="teknotok-ait-label"><?php echo esc_html( $switcher_languages[ $active_lang ] ?? $active_lang ); ?></span>
				<span class="teknotok-ait-arrow" aria-hidden="true"></span>
			</div>
			<ul class="teknotok-ait-languages-dropdown" role="listbox">
				<?php if ( $total_languages > 5 ) : ?>
					<li class="teknotok-ait-search-item">
						<input type="text" class="teknotok-ait-search-input" placeholder="<?php echo esc_attr( $this->get_switcher_search_copy( $active_lang, 'placeholder' ) ); ?>" aria-label="<?php echo esc_attr( $this->get_switcher_search_copy( $active_lang, 'label' ) ); ?>" autocomplete="off" dir="<?php echo esc_attr( $direction ); ?>" />
					</li>
				<?php endif; ?>
				<!-- Source Language -->
				<li class="<?php echo ( $active_lang === $source ) ? 'active' : ''; ?>" data-lang="<?php echo esc_attr( $source ); ?>" data-search-term="<?php echo esc_attr( $this->get_switcher_language_search_term( $source, $switcher_languages, $languages ) ); ?>" role="option" aria-selected="<?php echo $active_lang === $source ? 'true' : 'false'; ?>">
					<a href="<?php echo esc_url( \TeknoTok\AiTranslator\Frontend\UrlManager::get_source_language_switcher_url() ); ?>">
						<img src="<?php echo esc_url( self::get_flag_url( $source ) ); ?>" class="teknotok-ait-flag" alt="<?php echo esc_attr( $source ); ?>" />
						<?php echo esc_html( $switcher_languages[ $source ] ?? $source ); ?>
					</a>
				</li>
				<!-- Target Languages -->
				<?php foreach ( $targets as $lang ) : ?>
					<li class="<?php echo ( $active_lang === $lang ) ? 'active' : ''; ?>" data-lang="<?php echo esc_attr( $lang ); ?>" data-search-term="<?php echo esc_attr( $this->get_switcher_language_search_term( $lang, $switcher_languages, $languages ) ); ?>" role="option" aria-selected="<?php echo $active_lang === $lang ? 'true' : 'false'; ?>">
						<a href="<?php echo esc_url( \TeknoTok\AiTranslator\Frontend\UrlManager::get_clean_url_for_language( $lang ) ); ?>">
							<img src="<?php echo esc_url( self::get_flag_url( $lang ) ); ?>" class="teknotok-ait-flag" alt="<?php echo esc_attr( $lang ); ?>" />
							<?php echo esc_html( $switcher_languages[ $lang ] ?? $lang ); ?>
						</a>
					</li>
				<?php endforeach; ?>
				<?php if ( $show_referral ) : ?>
					<!-- Referral Link -->
					<li class="teknotok-ait-referral-item">
						<a href="https://soft.teknotok.com/teknotok-translator-pro/?utm_source=translator_widget&utm_medium=powered_by&utm_campaign=customer_sites" target="_blank" rel="noopener noreferrer nofollow sponsored" aria-label="<?php esc_attr_e( 'Powered by TeknoTok AI Translator.', 'teknotok-ai-translator' ); ?>">
							<span class="teknotok-ait-referral-title"><?php esc_html_e( 'Powered by TeknoTok', 'teknotok-ai-translator' ); ?></span>
						</a>
					</li>
				<?php endif; ?>
			</ul>
		</div>
		<?php
		return ob_get_clean();
	}

	/**
	 * Determine whether the switcher attribution should render.
	 *
	 * @param array $settings Plugin settings.
	 * @return bool
	 */
	private function should_show_referral( $settings ) {
		$hide_requested = isset( $settings['hide_powered_by'] ) && '1' === (string) $settings['hide_powered_by'];

		return ! ( $hide_requested && \TeknoTok\AiTranslator\Integrations\LicenseManager::is_premium_active() );
	}

	/**
	 * Build CSS variables for a saved design.
	 *
	 * @param array $design Sanitized design settings.
	 * @return string
	 */
	private function get_design_inline_style( $design ) {
		$opacity = max( 0.4, min( 1, (int) $design['switcher_opacity'] / 100 ) );
		$radius  = array(
			'pill'    => '999px',
			'rounded' => '12px',
			'square'  => '4px',
		);

		return sprintf(
			'--teknotok-switcher-bg:%1$s;--teknotok-switcher-bg-solid:%2$s;--teknotok-switcher-text:%3$s;--teknotok-switcher-border:%4$s;--teknotok-switcher-accent:%5$s;--teknotok-switcher-radius:%6$s;--teknotok-switcher-border-width:%7$dpx;',
			self::hex_to_rgba( $design['switcher_bg_color'], $opacity ),
			$design['switcher_bg_color'],
			$design['switcher_text_color'],
			$design['switcher_border_color'],
			$design['switcher_accent_color'],
			$radius[ $design['switcher_shape'] ] ?? '999px',
			(int) $design['switcher_border_width']
		);
	}

	/**
	 * Sanitize hex color with fallback.
	 *
	 * @param string $value    Raw color.
	 * @param string $fallback Fallback color.
	 * @return string
	 */
	private static function sanitize_hex_color( $value, $fallback ) {
		$value = trim( (string) $value );
		if ( preg_match( '/^#[0-9a-fA-F]{6}$/', $value ) ) {
			return strtolower( $value );
		}
		if ( preg_match( '/^#[0-9a-fA-F]{3}$/', $value ) ) {
			return strtolower( '#' . $value[1] . $value[1] . $value[2] . $value[2] . $value[3] . $value[3] );
		}

		return $fallback;
	}

	/**
	 * Convert a sanitized hex color to rgba.
	 *
	 * @param string $hex     Hex color.
	 * @param float  $opacity Opacity from 0 to 1.
	 * @return string
	 */
	private static function hex_to_rgba( $hex, $opacity ) {
		$hex = ltrim( $hex, '#' );
		return sprintf(
			'rgba(%d,%d,%d,%.2f)',
			hexdec( substr( $hex, 0, 2 ) ),
			hexdec( substr( $hex, 2, 2 ) ),
			hexdec( substr( $hex, 4, 2 ) ),
			$opacity
		);
	}

	/**
	 * Get visitor-facing language names for the switcher.
	 *
	 * The switcher is marked notranslate, so labels must be rendered as language
	 * autonyms instead of relying on page translation or plugin .mo files.
	 *
	 * @param array $fallback_languages Supported language names.
	 * @return array
	 */
	private function get_switcher_language_names( $fallback_languages ) {
		$native_names = array(
			'en'  => 'English',
			'es'  => 'Español',
			'tr'  => 'Türkçe',
			'zh'  => '中文',
			'hi'  => 'हिन्दी',
			'ar'  => 'العربية',
			'pt'  => 'Português',
			'bn'  => 'বাংলা',
			'ru'  => 'Русский',
			'ja'  => '日本語',
			'fr'  => 'Français',
			'de'  => 'Deutsch',
			'it'  => 'Italiano',
			'nl'  => 'Nederlands',
			'pl'  => 'Polski',
			'sv'  => 'Svenska',
			'vi'  => 'Tiếng Việt',
			'ko'  => '한국어',
			'id'  => 'Bahasa Indonesia',
			'el'  => 'Ελληνικά',
			'da'  => 'Dansk',
			'fi'  => 'Suomi',
			'no'  => 'Norsk',
			'cs'  => 'Čeština',
			'hu'  => 'Magyar',
			'ro'  => 'Română',
			'sk'  => 'Slovenčina',
			'uk'  => 'Українська',
			'bg'  => 'Български',
			'hr'  => 'Hrvatski',
			'sr'  => 'Српски',
			'sl'  => 'Slovenščina',
			'et'  => 'Eesti',
			'lv'  => 'Latviešu',
			'lt'  => 'Lietuvių',
			'th'  => 'ไทย',
			'ms'  => 'Bahasa Melayu',
			'fa'  => 'فارسی',
			'ur'  => 'اردو',
			'ta'  => 'தமிழ்',
			'te'  => 'తెలుగు',
			'ml'  => 'മലയാളം',
			'kn'  => 'ಕನ್ನಡ',
			'mr'  => 'मराठी',
			'gu'  => 'ગુજરાતી',
			'pa'  => 'ਪੰਜਾਬੀ',
			'sw'  => 'Kiswahili',
			'af'  => 'Afrikaans',
			'sq'  => 'Shqip',
			'am'  => 'አማርኛ',
			'hy'  => 'Հայերեն',
			'az'  => 'Azərbaycanca',
			'eu'  => 'Euskara',
			'be'  => 'Беларуская',
			'bs'  => 'Bosanski',
			'ca'  => 'Català',
			'ceb' => 'Cebuano',
			'ny'  => 'Chichewa',
			'co'  => 'Corsu',
			'eo'  => 'Esperanto',
			'fy'  => 'Frysk',
			'gl'  => 'Galego',
			'ka'  => 'ქართული',
			'haw' => 'ʻŌlelo Hawaiʻi',
			'hmn' => 'Hmoob',
			'is'  => 'Íslenska',
			'ig'  => 'Igbo',
			'ga'  => 'Gaeilge',
			'jv'  => 'Basa Jawa',
			'kk'  => 'Қазақ тілі',
			'km'  => 'ខ្មែរ',
			'ku'  => 'Kurdî',
			'ky'  => 'Кыргызча',
			'lo'  => 'ລາວ',
			'la'  => 'Latina',
			'lb'  => 'Lëtzebuergesch',
			'mk'  => 'Македонски',
			'mg'  => 'Malagasy',
			'mi'  => 'Māori',
			'mn'  => 'Монгол',
			'my'  => 'မြန်မာ',
			'ne'  => 'नेपाली',
			'ps'  => 'پښتو',
			'sm'  => 'Gagana Samoa',
			'gd'  => 'Gàidhlig',
			'st'  => 'Sesotho',
			'sn'  => 'Shona',
			'sd'  => 'سنڌي',
			'si'  => 'සිංහල',
			'so'  => 'Soomaali',
			'su'  => 'Basa Sunda',
			'tg'  => 'Тоҷикӣ',
			'tt'  => 'Татарча',
			'uz'  => 'Oʻzbekcha',
			'cy'  => 'Cymraeg',
			'xh'  => 'isiXhosa',
			'yi'  => 'ייִדיש',
			'yo'  => 'Yorùbá',
			'zu'  => 'isiZulu',
		);

		return array_replace( (array) $fallback_languages, $native_names );
	}

	/**
	 * Build a search term containing the language code and known display labels.
	 *
	 * @param string $lang               Language code.
	 * @param array  $switcher_languages Switcher language display names.
	 * @param array  $fallback_languages Supported language names.
	 * @return string
	 */
	private function get_switcher_language_search_term( $lang, $switcher_languages, $fallback_languages ) {
		$parts = array(
			$lang,
			$switcher_languages[ $lang ] ?? '',
			$fallback_languages[ $lang ] ?? '',
		);

		$parts = array_unique( array_filter( array_map( 'strval', $parts ) ) );

		return trim( implode( ' ', $parts ) );
	}

	/**
	 * Get visitor-facing search input copy for the active switcher language.
	 *
	 * The switcher is excluded from automatic page translation, so this copy
	 * needs to follow the selected language directly instead of using the
	 * WordPress admin locale.
	 *
	 * @param string $active_lang Active language code.
	 * @param string $part        Copy part: placeholder or label.
	 * @return string
	 */
	private function get_switcher_search_copy( $active_lang, $part ) {
		$copies = array(
			'en' => array(
				'placeholder' => 'Search language...',
				'label'       => 'Search language',
			),
			'es' => array(
				'placeholder' => 'Buscar idioma...',
				'label'       => 'Buscar idioma',
			),
			'tr' => array(
				'placeholder' => 'Dil ara...',
				'label'       => 'Dil ara',
			),
			'zh' => array(
				'placeholder' => '搜索语言...',
				'label'       => '搜索语言',
			),
			'hi' => array(
				'placeholder' => 'भाषा खोजें...',
				'label'       => 'भाषा खोजें',
			),
			'ar' => array(
				'placeholder' => 'ابحث عن لغة...',
				'label'       => 'ابحث عن لغة',
			),
			'pt' => array(
				'placeholder' => 'Pesquisar idioma...',
				'label'       => 'Pesquisar idioma',
			),
			'bn' => array(
				'placeholder' => 'ভাষা খুঁজুন...',
				'label'       => 'ভাষা খুঁজুন',
			),
			'ru' => array(
				'placeholder' => 'Поиск языка...',
				'label'       => 'Поиск языка',
			),
			'ja' => array(
				'placeholder' => '言語を検索...',
				'label'       => '言語を検索',
			),
			'fr' => array(
				'placeholder' => 'Rechercher une langue...',
				'label'       => 'Rechercher une langue',
			),
			'de' => array(
				'placeholder' => 'Sprache suchen...',
				'label'       => 'Sprache suchen',
			),
			'pl' => array(
				'placeholder' => 'Szukaj języka...',
				'label'       => 'Szukaj języka',
			),
		);

		$copy = $copies[ $active_lang ] ?? $copies['en'];

		return $copy[ $part ] ?? $copies['en'][ $part ];
	}

	/**
	 * Determine whether the switcher chrome should render right-to-left.
	 *
	 * @param string $lang Language code.
	 * @return bool
	 */
	private function is_rtl_language( $lang ) {
		return in_array( $lang, array( 'ar', 'fa', 'ur', 'ps', 'sd', 'yi' ), true );
	}

	/**
	 * Sort selected target languages by customer-facing priority.
	 *
	 * @param array  $targets Selected target language codes.
	 * @param string $source Source language code.
	 * @param array  $languages Supported language map.
	 * @return array
	 */
	private function sort_switcher_targets( $targets, $source, $languages ) {
		return \TeknoTok\AiTranslator\Plugin::normalize_target_languages( $targets, $source );
	}

	/**
	 * Shortcode callback.
	 *
	 * @return string
	 */
	public function render_switcher_shortcode() {
		return $this->render_switcher_html();
	}

	/**
	 * Render floating switcher overlay in footer.
	 *
	 * @return void
	 */
	public function render_floating_switcher() {
		$settings = get_option( 'teknotok_ait_settings', array() );
		$position = $settings['switcher_position'] ?? 'floating-bottom-right';

		if ( 'shortcode' === $position ) {
			return;
		}

		$class = 'teknotok-ait-floating-' . $position;
		$html = $this->render_switcher_html();

		if ( ! empty( $html ) ) {
			echo '<div class="teknotok-ait-floating-wrapper ' . esc_attr( $class ) . ' notranslate" translate="no">' . $html . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		}
	}

	/**
	 * Get the flag image URL from FlagCDN.
	 *
	 * @param string $lang Language code.
	 * @return string Flag image URL.
	 */
	public static function get_flag_url( $lang ) {
		$mapping = array(
			'en'  => 'gb', // English -> UK
			'ar'  => 'sa', // Arabic -> Saudi Arabia
			'zh'  => 'cn', // Chinese -> China
			'hi'  => 'in', // Hindi -> India
			'ja'  => 'jp', // Japanese -> Japan
			'ko'  => 'kr', // Korean -> South Korea
			'da'  => 'dk', // Danish -> Denmark
			'sv'  => 'se', // Swedish -> Sweden
			'vi'  => 'vn', // Vietnamese -> Vietnam
			'el'  => 'gr', // Greek -> Greece
			'uk'  => 'ua', // Ukrainian -> Ukraine
			'cs'  => 'cz', // Czech -> Czechia
			'ur'  => 'pk', // Urdu -> Pakistan
			'bn'  => 'bd', // Bengali -> Bangladesh
			'fa'  => 'ir', // Persian -> Iran
			'sq'  => 'al', // Albanian -> Albania
			'hy'  => 'am', // Armenian -> Armenia
			'et'  => 'ee', // Estonian -> Estonia
			'ms'  => 'my', // Malay -> Malaysia
			'my'  => 'mm', // Burmese (Myanmar) -> Myanmar
			'ny'  => 'mw', // Chichewa -> Malawi
			'ka'  => 'ge', // Georgian -> Georgia
			'ne'  => 'np', // Nepali -> Nepal
			'pa'  => 'in', // Punjabi -> India
			'su'  => 'id', // Sundanese -> Indonesia
			'jv'  => 'id', // Javanese -> Indonesia
			'sw'  => 'ke', // Swahili -> Kenya
			'af'  => 'za', // Afrikaans -> South Africa
			'xh'  => 'za', // Xhosa -> South Africa
			'zu'  => 'za', // Zulu -> South Africa
			'am'  => 'et', // Amharic -> Ethiopia
			'bs'  => 'ba', // Bosnian -> Bosnia
			'ca'  => 'es', // Catalan -> Spain
			'fy'  => 'nl', // Frisian -> Netherlands
			'gl'  => 'es', // Galician -> Spain
			'ig'  => 'ng', // Igbo -> Nigeria
			'yo'  => 'ng', // Yoruba -> Nigeria
			'ga'  => 'ie', // Irish -> Ireland
			'kk'  => 'kz', // Kazakh -> Kazakhstan
			'km'  => 'kh', // Khmer -> Cambodia
			'ku'  => 'tr', // Kurdish -> Turkey
			'ky'  => 'kg', // Kyrgyz -> Kyrgyzstan
			'lo'  => 'la', // Lao -> Laos
			'la'  => 'va', // Latin -> Vatican City
			'lb'  => 'lu', // Luxembourgish -> Luxembourg
			'mk'  => 'mk', // Macedonian -> North Macedonia
			'mg'  => 'mg', // Malagasy -> Madagascar
			'mi'  => 'nz', // Maori -> New Zealand
			'mn'  => 'mn', // Mongolian -> Mongolia
			'ps'  => 'af', // Pashto -> Afghanistan
			'sm'  => 'ws', // Samoan -> Samoa
			'gd'  => 'gb', // Scots Gaelic -> UK
			'st'  => 'za', // Sesotho -> South Africa
			'sn'  => 'zw', // Shona -> Zimbabwe
			'sd'  => 'pk', // Sindhi -> Pakistan
			'si'  => 'lk', // Sinhala -> Sri Lanka
			'so'  => 'so', // Somali -> Somalia
			'tg'  => 'tj', // Tajik -> Tajikistan
			'tt'  => 'ru', // Tatar -> Russia
			'uz'  => 'uz', // Uzbek -> Uzbekistan
			'cy'  => 'gb', // Welsh -> UK
			'yi'  => 'il', // Yiddish -> Israel
		);
		$code = $mapping[ $lang ] ?? $lang;
		return 'https://flagcdn.com/w40/' . $code . '.png';
	}
}
