<?php
namespace TeknoTok\AiTranslator\Frontend;

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

use TeknoTok\AiTranslator\Database\MemoryRepository;
use TeknoTok\AiTranslator\Database\JobRepository;

/**
 * Filter manager to translate frontend strings dynamically.
 */
class TranslationFilters {
	/**
	 * Constructor. Registers translation hooks.
	 */
	public function __construct() {
		if ( is_admin() ) {
			return;
		}

		// Always output hreflang tags on frontend requests
		add_action( 'wp_head', array( $this, 'render_hreflang_tags' ) );

		// Only apply translation filters if active language differs from default
		$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 ) {
			add_filter( 'the_title', array( $this, 'translate_title' ), 10, 2 );
			add_filter( 'the_content', array( $this, 'translate_content' ), 1 );
			add_filter( 'the_excerpt', array( $this, 'translate_excerpt' ) );
			add_filter( 'wp_get_nav_menu_items', array( $this, 'translate_menu_items' ) );
			add_filter( 'get_post_metadata', array( $this, 'translate_metadata' ), 10, 4 );
			add_filter( 'gettext', array( $this, 'translate_gettext' ), 10, 3 );
			add_action( 'template_redirect', array( $this, 'start_output_buffering' ) );
			add_action( 'template_redirect', array( $this, 'disable_external_caching' ), 5 );
		}
	}

	/**
	 * Translate the page/post title.
	 *
	 * @param string $title   Original title.
	 * @param int    $post_id Post ID.
	 * @return string Translated title.
	 */
	public function translate_title( $title, $post_id = 0 ) {
		if ( empty( $title ) || ! $post_id ) {
			return $title;
		}

		$active_lang = \TeknoTok\AiTranslator\Plugin::get_active_language();
		$cached = MemoryRepository::get_translation( $title, $active_lang );

		if ( false !== $cached ) {
			return $cached;
		}

		// Queue job if not cached
		if ( \TeknoTok\AiTranslator\Plugin::is_ready_for_translations() ) {
			JobRepository::add_job( 'post', $post_id, $active_lang );
		}

		return $title;
	}

	/**
	 * Translate post content.
	 *
	 * @param string $content Original content.
	 * @return string Translated content.
	 */
	public function translate_content( $content ) {
		if ( empty( $content ) ) {
			return $content;
		}

		global $post;
		if ( ! $post ) {
			return $content;
		}

		$active_lang = \TeknoTok\AiTranslator\Plugin::get_active_language();
		$cached = MemoryRepository::get_translation( $content, $active_lang );

		if ( false !== $cached ) {
			return $cached;
		}

		if ( \TeknoTok\AiTranslator\Plugin::is_ready_for_translations() ) {
			JobRepository::add_job( 'post', $post->ID, $active_lang );
		}

		return $content;
	}

	/**
	 * Translate post excerpt.
	 *
	 * @param string $excerpt Original excerpt.
	 * @return string Translated excerpt.
	 */
	public function translate_excerpt( $excerpt ) {
		if ( empty( $excerpt ) ) {
			return $excerpt;
		}

		global $post;
		if ( ! $post ) {
			return $excerpt;
		}

		$active_lang = \TeknoTok\AiTranslator\Plugin::get_active_language();
		$cached = MemoryRepository::get_translation( $excerpt, $active_lang );

		if ( false !== $cached ) {
			return $cached;
		}

		if ( \TeknoTok\AiTranslator\Plugin::is_ready_for_translations() ) {
			JobRepository::add_job( 'post', $post->ID, $active_lang );
		}

		return $excerpt;
	}

	/**
	 * Translate navigation menu items.
	 *
	 * @param array $items List of menu items.
	 * @return array Translated menu items.
	 */
	public function translate_menu_items( $items ) {
		if ( empty( $items ) ) {
			return $items;
		}

		$active_lang = \TeknoTok\AiTranslator\Plugin::get_active_language();

		foreach ( $items as $item ) {
			$title = $item->title;
			if ( empty( $title ) ) {
				continue;
			}

			$cached = MemoryRepository::get_translation( $title, $active_lang );
			if ( false !== $cached ) {
				$item->title = $cached;
			} else {
				if ( ! $this->is_warmup_request() && 'post_type' === $item->type && \TeknoTok\AiTranslator\Plugin::is_ready_for_translations() ) {
					JobRepository::add_job( 'post', $item->object_id, $active_lang );
				}
				if ( ! $this->is_warmup_request() && \TeknoTok\AiTranslator\Plugin::is_ready_for_translations() ) {
					JobRepository::add_string_job( $title, $active_lang );
				}
			}
		}

		return $items;
	}

	/**
	 * Intercept metadata lookups (e.g. WooCommerce product descriptions, short descriptions).
	 *
	 * @param mixed  $value     Meta value.
	 * @param int    $object_id Object ID.
	 * @param string $meta_key  Meta key.
	 * @param bool   $single    Single value flag.
	 * @return mixed Translated metadata.
	 */
	public function translate_metadata( $value, $object_id, $meta_key, $single ) {
		$seo_whitelist = array(
			'_yoast_wpseo_title',
			'_yoast_wpseo_metadesc',
			'_metaseo_description',
			'rank_math_title',
			'rank_math_description',
			'rank_math_focus_keyword',
		);

		$is_translatable = false;
		if ( strpos( $meta_key, '_' ) !== 0 ) {
			$is_translatable = true;
		} elseif ( in_array( $meta_key, $seo_whitelist, true ) ) {
			$is_translatable = true;
		}

		if ( ! $is_translatable ) {
			return $value;
		}

		// Prevent infinite recursion loops by temporarily unhooking the filter
		remove_filter( 'get_post_metadata', array( $this, 'translate_metadata' ), 10 );
		$original_meta = get_post_meta( $object_id, $meta_key, $single );
		add_filter( 'get_post_metadata', array( $this, 'translate_metadata' ), 10, 4 );

		if ( empty( $original_meta ) ) {
			return $value;
		}

		$active_lang = \TeknoTok\AiTranslator\Plugin::get_active_language();
		$cache_miss = false;

		if ( is_array( $original_meta ) ) {
			// Check if single-level (flat) array. Skip recursive/multidimensional array translation.
			$is_flat = true;
			foreach ( $original_meta as $item ) {
				if ( is_array( $item ) || is_object( $item ) ) {
					$is_flat = false;
					break;
				}
			}

			if ( ! $is_flat ) {
				return $original_meta;
			}

			$translated_meta = array();
			foreach ( $original_meta as $k => $v ) {
				if ( is_string( $v ) && ! empty( trim( $v ) ) && ! is_numeric( $v ) ) {
					$cached = MemoryRepository::get_translation( $v, $active_lang );
					if ( false !== $cached ) {
						$translated_meta[$k] = $cached;
					} else {
						$translated_meta[$k] = $v;
						$cache_miss = true;
					}
				} else {
					$translated_meta[$k] = $v;
				}
			}

			if ( $cache_miss && \TeknoTok\AiTranslator\Plugin::is_ready_for_translations() ) {
				JobRepository::add_job( 'post', $object_id, $active_lang );
			}

			return $single ? array( $translated_meta ) : $translated_meta;
		}

		if ( is_string( $original_meta ) ) {
			if ( empty( trim( $original_meta ) ) || is_numeric( $original_meta ) ) {
				return $single ? $original_meta : array( $original_meta );
			}

			$cached = MemoryRepository::get_translation( $original_meta, $active_lang );
			if ( false !== $cached ) {
				return $single ? $cached : array( $cached );
			}

			if ( \TeknoTok\AiTranslator\Plugin::is_ready_for_translations() ) {
				JobRepository::add_job( 'post', $object_id, $active_lang );
			}
			return $single ? $original_meta : array( $original_meta );
		}

		return $value;
	}

	/**
	 * Translate whitelisted theme and plugin strings.
	 *
	 * @param string $translated The translated text.
	 * @param string $text       The original text.
	 * @param string $domain     The textdomain identifier.
	 * @return string Translated string if cached, otherwise original.
	 */
	public function translate_gettext( $translated, $text, $domain ) {
		if ( empty( $text ) ) {
			return $translated;
		}

		$theme = wp_get_theme();
		$theme_domain = $theme ? $theme->get( 'TextDomain' ) : '';

		// Whitelist theme and woocommerce text domains to avoid overloading database lookups
		$whitelisted_domains = array(
			'woocommerce',
			'twentytwentyfour',
			get_template(),
			get_stylesheet(),
		);

		if ( ! empty( $theme_domain ) ) {
			$whitelisted_domains[] = $theme_domain;
		}

		if ( ! in_array( $domain, $whitelisted_domains, true ) ) {
			return $translated;
		}

		$active_lang = \TeknoTok\AiTranslator\Plugin::get_active_language();
		$cached = MemoryRepository::get_translation( $text, $active_lang );

		if ( false !== $cached ) {
			return $cached;
		}

		return $translated;
	}

	/**
	 * Start output buffering to capture the entire HTML page.
	 *
	 * @return void
	 */
	public function start_output_buffering() {
		ob_start( array( $this, 'translate_page_output' ) );
	}

	/**
	 * Disable third-party page caching systems on translated pages.
	 * This prevents page-cache language mixing and ensures translations work correctly.
	 *
	 * @return void
	 */
	public function disable_external_caching() {
		if ( is_admin() ) {
			return;
		}

		// 1. Standard WordPress / WP Rocket / W3 Total Cache / Super Cache
		if ( ! defined( 'DONOTCACHEPAGE' ) ) {
			define( 'DONOTCACHEPAGE', true );
		}

		// 2. LiteSpeed Cache
		if ( ! defined( 'LITESPEED_DISABLE_ALL' ) ) {
			define( 'LITESPEED_DISABLE_ALL', true );
		}
		if ( class_exists( '\LiteSpeed_Cache_API' ) || has_action( 'litespeed_control_set_nocache' ) ) {
			do_action( 'litespeed_control_set_nocache' );
		}

		// 3. Clear/prevent browser or CDN caching (Varnish, Cloudflare, etc.)
		if ( ! headers_sent() ) {
			nocache_headers();
		}
	}

	/**
	 * Callback to parse and translate the entire captured HTML page or AJAX fragments.
	 *
	 * @param string $buffer Raw page HTML or JSON.
	 * @return string Translated HTML or JSON.
	 */
	public function translate_page_output( $buffer ) {
		if ( empty( $buffer ) ) {
			return $buffer;
		}

		$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 $buffer;
		}

		try {
			$queue_all_targets   = false;
			$shared_chrome_only = false;

			// 1. Handle WooCommerce AJAX JSON responses (containing HTML fragments)
			if ( isset( $_GET['wc-ajax'] ) ) {
				$decoded = json_decode( $buffer, true );
				if ( is_array( $decoded ) ) {
					if ( isset( $decoded['fragments'] ) && is_array( $decoded['fragments'] ) ) {
						foreach ( $decoded['fragments'] as $selector => $html ) {
							if ( ! empty( $html ) && is_string( $html ) ) {
								$decoded['fragments'][ $selector ] = \TeknoTok\AiTranslator\Utils\HtmlParser::translate_html( $html, $source_lang, $active_lang, null, false, true, $queue_all_targets, $shared_chrome_only );
							}
						}
					}
					return json_encode( $decoded );
				}
			}

			// 2. Handle standard HTML pages or AJAX HTML fragments
			$is_html = ( false !== stripos( $buffer, '<html' ) );
			$is_wc_ajax_html = isset( $_GET['wc-ajax'] ) && ( false !== stripos( $buffer, '<div' ) || false !== stripos( $buffer, '<table' ) || false !== stripos( $buffer, '<form' ) );

			if ( $is_html || $is_wc_ajax_html ) {
				return \TeknoTok\AiTranslator\Utils\HtmlParser::translate_html( $buffer, $source_lang, $active_lang, null, false, true, $queue_all_targets, $shared_chrome_only );
			}
		} catch ( \Exception $e ) {
			return $buffer;
		}

		return $buffer;
	}

	/**
	 * Check whether the current frontend request is a background warmup render.
	 *
	 * @return bool True for warmup requests.
	 */
	private function is_warmup_request() {
		return ! empty( $_GET['teknotok_ait_warmup'] ) || ! empty( $_SERVER['HTTP_X_TEKNOTOK_WARMUP'] );
	}

	/**
	 * Output alternate hreflang tags for target languages in the head.
	 *
	 * @return void
	 */
	public function render_hreflang_tags() {
		$settings = get_option( 'teknotok_ait_settings', array() );
		$source = $settings['source_language'] ?? 'en';
		$targets = $settings['target_languages'] ?? array();

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

		$all_langs = array_merge( array( $source ), $targets );
		foreach ( $all_langs as $lang ) {
			$url = \TeknoTok\AiTranslator\Frontend\UrlManager::get_clean_url_for_language( $lang );
			printf(
				'<link rel="alternate" hreflang="%s" href="%s" />' . "\n",
				esc_attr( $lang ),
				esc_url( $url )
			);
		}

		// Output x-default pointing to the source language version
		$default_url = \TeknoTok\AiTranslator\Frontend\UrlManager::get_clean_url_for_language( $source );
		printf(
			'<link rel="alternate" hreflang="x-default" href="%s" />' . "\n",
			esc_url( $default_url )
		);
	}
}
