<?php
namespace TeknoTok\AiTranslator\Integrations;

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

use TeknoTok\AiTranslator\Database\MemoryRepository;

/**
 * WooCommerce translation integration logic.
 */
class WooCommerceIntegration {
	/**
	 * Constructor. Registers hooks if WooCommerce is active.
	 */
	public function __construct() {
		if ( is_admin() ) {
			return;
		}

		add_action( 'woocommerce_init', array( $this, 'register_frontend_hooks' ) );
	}

	/**
	 * Register WooCommerce frontend hooks once WC is loaded.
	 *
	 * @return void
	 */
	public function register_frontend_hooks() {

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

		add_filter( 'woocommerce_attribute_label', array( $this, 'translate_attribute_label' ), 10, 3 );
		add_filter( 'woocommerce_cart_item_name', array( $this, 'translate_cart_item_name' ), 10, 3 );
		add_filter( 'woocommerce_checkout_fields', array( $this, 'translate_checkout_fields' ), 20 );
		add_filter( 'woocommerce_form_field_args', array( $this, 'translate_form_field_args' ), 20, 3 );
		add_filter( 'woocommerce_gateway_description', array( $this, 'translate_payment_gateway_description' ), 20, 2 );
		add_filter( 'woocommerce_gateway_title', array( $this, 'translate_payment_gateway_title' ), 20, 2 );
		add_filter( 'woocommerce_store_api_cart_item', array( $this, 'translate_store_api_cart_item' ), 10, 3 );
		add_filter( 'woocommerce_store_api_product_response', array( $this, 'translate_store_api_product_response' ), 10, 3 );
		add_filter( 'load_script_translations', array( $this, 'merge_woocommerce_block_translations' ), 10, 4 );
		add_filter( 'woocommerce_product_get_name', array( $this, 'translate_product_name' ), 10, 2 );
		add_filter( 'woocommerce_product_get_title', array( $this, 'translate_product_name' ), 10, 2 );
		add_filter( 'woocommerce_product_get_short_description', array( $this, 'translate_product_short_description' ), 10, 2 );
		add_filter( 'woocommerce_product_get_description', array( $this, 'translate_product_description' ), 10, 2 );
	}

	/**
	 * Translate custom product attribute labels.
	 *
	 * @param string $label        Attribute label.
	 * @param string $name         Attribute name.
	 * @param object $product      WC Product object.
	 * @return string Translated label.
	 */
	public function translate_attribute_label( $label, $name, $product ) {
		$active_lang = \TeknoTok\AiTranslator\Plugin::get_active_language();
		$cached = $this->get_memory_translation( $label, $active_lang );
		return ( false !== $cached ) ? $cached : $label;
	}

	/**
	 * Translate product names in cart layouts.
	 *
	 * @param string $name          Item name wrapper.
	 * @param array  $cart_item     Cart item details.
	 * @param string $cart_item_key Cart item unique key.
	 * @return string Translated link HTML.
	 */
	public function translate_cart_item_name( $name, $cart_item, $cart_item_key ) {
		$active_lang = \TeknoTok\AiTranslator\Plugin::get_active_language();
		
		$product = $cart_item['data'];
		$title = $this->get_source_product_name( $product );
		
		$cached = $this->get_memory_translation( $title, $active_lang );
		if ( false !== $cached ) {
			$permalink = $product->get_permalink( $cart_item );
			if ( $permalink ) {
				return sprintf( '<a href="%s">%s</a>', esc_url( $permalink ), esc_html( $cached ) );
			}
			return esc_html( $cached );
		}

		return $name;
	}

	/**
	 * Translate product names returned by the WooCommerce Blocks Store API.
	 *
	 * @param array  $item          Store API cart item response.
	 * @param array  $cart_item     Cart item details.
	 * @param string $cart_item_key Cart item unique key.
	 * @return array Cart item response.
	 */
	public function translate_store_api_cart_item( $item, $cart_item = array(), $cart_item_key = '' ) {
		if ( empty( $item ) || ! is_array( $item ) || empty( $cart_item['data'] ) ) {
			return $item;
		}

		$product = $cart_item['data'];
		$title   = $this->get_source_product_name( $product );
		if ( empty( $title ) ) {
			return $item;
		}

		$active_lang = \TeknoTok\AiTranslator\Plugin::get_active_language();
		$cached      = $this->get_memory_translation( $title, $active_lang );

		if ( false !== $cached ) {
			$item['name'] = $cached;
		}

		foreach ( array( 'description', 'short_description' ) as $description_key ) {
			if ( isset( $item[ $description_key ] ) && is_string( $item[ $description_key ] ) ) {
				$source_field = 'short_description' === $description_key ? 'short_description' : 'description';
				$item[ $description_key ] = $this->translate_product_body_value( $item[ $description_key ], $product, $source_field, $active_lang );
			}
		}

		return $item;
	}

	/**
	 * Translate WooCommerce Blocks product response body fields.
	 *
	 * @param mixed       $response Store API product response.
	 * @param \WC_Product $product  Product object.
	 * @param mixed       $request  REST request object.
	 * @return mixed Updated response.
	 */
	public function translate_store_api_product_response( $response, $product = null, $request = null ) {
		if ( empty( $response ) ) {
			return $response;
		}

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

		if ( is_object( $response ) && method_exists( $response, 'get_data' ) && method_exists( $response, 'set_data' ) ) {
			$data = $response->get_data();
			if ( is_array( $data ) ) {
				$response->set_data( $this->translate_product_response_body_fields( $data, $product, $active_lang ) );
			}
			return $response;
		}

		if ( is_array( $response ) ) {
			return $this->translate_product_response_body_fields( $response, $product, $active_lang );
		}

		return $response;
	}

	/**
	 * Translate checkout field labels, placeholders, and descriptions.
	 *
	 * @param array $fields Checkout field groups.
	 * @return array Translated checkout field groups.
	 */
	public function translate_checkout_fields( $fields ) {
		if ( empty( $fields ) || ! is_array( $fields ) ) {
			return $fields;
		}

		foreach ( $fields as $group_key => $group_fields ) {
			if ( ! is_array( $group_fields ) ) {
				continue;
			}

			foreach ( $group_fields as $field_key => $field_args ) {
				if ( ! is_array( $field_args ) ) {
					continue;
				}

				$fields[ $group_key ][ $field_key ] = $this->translate_form_field_args( $field_args, $field_key, '' );
			}
		}

		return $fields;
	}

	/**
	 * Translate WooCommerce form field labels, placeholders, and descriptions.
	 *
	 * @param array  $args  Field render arguments.
	 * @param string $key   Field key.
	 * @param mixed  $value Current field value.
	 * @return array Translated field render arguments.
	 */
	public function translate_form_field_args( $args, $key, $value ) {
		if ( empty( $args ) || ! is_array( $args ) ) {
			return $args;
		}

		$active_lang = \TeknoTok\AiTranslator\Plugin::get_active_language();
		foreach ( array( 'label', 'placeholder', 'description' ) as $text_key ) {
			if ( isset( $args[ $text_key ] ) ) {
				$args[ $text_key ] = $this->translate_plain_display_text( $args[ $text_key ], $active_lang );
			}
		}

		return $args;
	}

	/**
	 * Translate payment gateway titles.
	 *
	 * @param string $title      Gateway title.
	 * @param string $gateway_id Gateway ID.
	 * @return string Translated title.
	 */
	public function translate_payment_gateway_title( $title, $gateway_id ) {
		return $this->translate_plain_display_text( $title );
	}

	/**
	 * Translate payment gateway descriptions.
	 *
	 * @param string $description Gateway description.
	 * @param string $gateway_id  Gateway ID.
	 * @return string Translated description.
	 */
	public function translate_payment_gateway_description( $description, $gateway_id ) {
		return $this->translate_plain_display_text( $description );
	}

	/**
	 * Dynamically merge WooCommerce block script translation JSON files for Gutenberg interactivity.
	 *
	 * @param string|false $translations JSON string of translations.
	 * @param string       $file         Path to the translation file.
	 * @param string       $handle       Script handle.
	 * @param string       $domain       Textdomain.
	 * @return string JSON translation data.
	 */
	public function merge_woocommerce_block_translations( $translations, $file, $handle, $domain ) {
		if ( 'woocommerce' !== $domain ) {
			return $translations;
		}

		// Only target WooCommerce block-related scripts
		if ( 0 !== strpos( $handle, 'wc-cart-checkout' ) && 0 !== strpos( $handle, 'wc-block' ) ) {
			return $translations;
		}

		$locale = determine_locale();
		$transient_key = 'teknotok_ait_wc_js_' . $locale;
		$cached_json = get_transient( $transient_key );

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

		$languages_dir = defined( 'WP_LANG_DIR' ) ? WP_LANG_DIR . '/plugins/' : WP_CONTENT_DIR . '/languages/plugins/';
		$pattern = $languages_dir . 'woocommerce-' . $locale . '-*.json';
		$files = glob( $pattern );

		if ( empty( $files ) ) {
			return $translations;
		}

		$merged_data = array();
		if ( ! empty( $translations ) ) {
			$decoded = json_decode( $translations, true );
			if ( is_array( $decoded ) ) {
				$merged_data = $decoded;
			}
		}

		if ( empty( $merged_data ) ) {
			$merged_data = array(
				'domain'      => 'messages',
				'locale_data' => array(
					'messages' => array(
						'' => array(
							'domain'       => 'messages',
							'plural-forms' => 'nplurals=2; plural=n > 1;',
							'lang'         => substr( $locale, 0, 2 ),
						),
					),
				),
			);
		}

		if ( ! isset( $merged_data['locale_data']['messages'] ) ) {
			$merged_data['locale_data']['messages'] = array();
		}

		foreach ( $files as $json_file ) {
			if ( ! is_file( $json_file ) || ! is_readable( $json_file ) ) {
				continue;
			}
			$content = file_get_contents( $json_file );
			if ( ! $content ) {
				continue;
			}
			$decoded = json_decode( $content, true );
			if ( ! is_array( $decoded ) || ! isset( $decoded['locale_data'] ) ) {
				continue;
			}

			foreach ( $decoded['locale_data'] as $sub_domain => $data ) {
				if ( ! is_array( $data ) ) {
					continue;
				}
				foreach ( $data as $key => $val ) {
					if ( '' === $key ) {
						continue;
					}
					$merged_data['locale_data']['messages'][ $key ] = $val;
				}
			}
		}

		$output_json = json_encode( $merged_data );
		// Cache the merged translation payload for 1 day
		set_transient( $transient_key, $output_json, DAY_IN_SECONDS );

		return $output_json;
	}

	/**
	 * Translate product property on the fly.
	 *
	 * @param string      $value   Original property value.
	 * @param \WC_Product $product WooCommerce Product object.
	 * @param string      $type    Type of text ('title' or 'content').
	 * @return string Translated property value.
	 */
	private function translate_product_property( $value, $product, $type = 'title' ) {
		if ( empty( $value ) || ! $product ) {
			return $value;
		}

		static $is_translating = false;
		if ( $is_translating ) {
			return $value;
		}
		$is_translating = true;

		$active_lang = \TeknoTok\AiTranslator\Plugin::get_active_language();
		$cached = $this->get_memory_translation( $value, $active_lang );

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

		if ( in_array( $type, array( 'short_description', 'description' ), true ) ) {
			$cached = $this->get_source_product_body_translation( $product, $type, $active_lang );
			if ( false !== $cached ) {
				$is_translating = false;
				return $cached;
			}
		}

		if ( $this->is_cart_checkout_display_request() ) {
			$is_translating = false;
			return $value;
		}

		// Queue product for translation on cache miss outside cart/checkout display surfaces.
		$product_id = $product->get_id();
		if ( $product_id && \TeknoTok\AiTranslator\Plugin::is_ready_for_translations() ) {
			\TeknoTok\AiTranslator\Database\JobRepository::add_job( 'post', $product_id, $active_lang );
		}

		$is_translating = false;
		return $value;
	}

	/**
	 * Translate product response description fields from saved product source fields.
	 *
	 * @param array       $data        Store API response data.
	 * @param \WC_Product $product     Product object.
	 * @param string      $active_lang Active target language.
	 * @return array Updated response data.
	 */
	private function translate_product_response_body_fields( $data, $product, $active_lang ) {
		foreach ( array( 'description', 'short_description' ) as $field ) {
			if ( isset( $data[ $field ] ) && is_string( $data[ $field ] ) ) {
				$data[ $field ] = $this->translate_product_body_value( $data[ $field ], $product, $field, $active_lang );
			}
		}

		if ( isset( $data['summary'] ) && is_string( $data['summary'] ) ) {
			$data['summary'] = $this->translate_product_body_value( $data['summary'], $product, 'short_description', $active_lang );
		}

		return $data;
	}

	/**
	 * Translate a rendered product body value using the exact source field cached by queue jobs.
	 *
	 * @param string      $value       Rendered value.
	 * @param \WC_Product $product     Product object.
	 * @param string      $field       Product body field.
	 * @param string      $active_lang Active target language.
	 * @return string Translated value when cached.
	 */
	private function translate_product_body_value( $value, $product, $field, $active_lang ) {
		$cached = $this->get_memory_translation( $value, $active_lang );
		if ( false !== $cached ) {
			return $cached;
		}

		$cached = $this->get_source_product_body_translation( $product, $field, $active_lang );
		if ( false !== $cached ) {
			return $cached;
		}

		return $value;
	}

	/**
	 * Read product body translation from the raw source post field.
	 *
	 * @param \WC_Product $product     Product object.
	 * @param string      $field       Product body field.
	 * @param string      $active_lang Active target language.
	 * @return string|false Translated product body.
	 */
	private function get_source_product_body_translation( $product, $field, $active_lang ) {
		$source = $this->get_source_product_body_text( $product, $field );
		if ( '' === trim( $source ) ) {
			return false;
		}

		$cached = $this->get_memory_translation( $source, $active_lang );
		if ( false !== $cached ) {
			return \TeknoTok\AiTranslator\Utils\HtmlParser::repair_inline_anchor_spacing( $cached, $active_lang );
		}

		return false;
	}

	/**
	 * Get source-language product body field without triggering WooCommerce filters.
	 *
	 * @param \WC_Product $product WooCommerce product object.
	 * @param string      $field   Product body field.
	 * @return string Source text.
	 */
	private function get_source_product_body_text( $product, $field ) {
		if ( ! $product || ! is_object( $product ) || ! method_exists( $product, 'get_id' ) ) {
			return '';
		}

		$product_id = (int) $product->get_id();
		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 ) {
			return '';
		}

		$post_field = 'short_description' === $field ? 'post_excerpt' : 'post_content';
		$value      = get_post_field( $post_field, $product_id );

		return is_string( $value ) ? $value : '';
	}

	/**
	 * Get the source-language product name without triggering WooCommerce name filters.
	 *
	 * @param \WC_Product $product WooCommerce product object.
	 * @return string Source product name.
	 */
	private function get_source_product_name( $product ) {
		if ( ! $product || ! is_object( $product ) || ! method_exists( $product, 'get_id' ) ) {
			return '';
		}

		$product_id = (int) $product->get_id();
		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 ) {
			$title = get_post_field( 'post_title', $product_id );
			if ( is_string( $title ) && '' !== trim( $title ) ) {
				return $title;
			}
		}

		return method_exists( $product, 'get_name' ) ? (string) $product->get_name() : '';
	}

	/**
	 * Translate plain display text from memory without queueing checkout/cart jobs.
	 *
	 * @param mixed       $text        Text to translate.
	 * @param string|null $active_lang Active target language.
	 * @return mixed Translated text when available.
	 */
	private function translate_plain_display_text( $text, $active_lang = null ) {
		if ( ! is_string( $text ) || '' === trim( $text ) ) {
			return $text;
		}

		if ( preg_match( '/<[^>]+>/', $text ) ) {
			return $text;
		}

		if ( ! preg_match( '/[[:alpha:]]/u', $text ) ) {
			return $text;
		}

		$active_lang = $active_lang ?: \TeknoTok\AiTranslator\Plugin::get_active_language();
		$cached      = $this->get_memory_translation( $text, $active_lang );
		if ( false !== $cached ) {
			return $cached;
		}

		return $text;
	}

	/**
	 * Read a translation from memory using common WooCommerce text variants.
	 *
	 * @param string $source_text Source text.
	 * @param string $active_lang Target language.
	 * @return string|false Translated text when cached.
	 */
	private function get_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 = MemoryRepository::get_translation( $variant, $active_lang );
			if ( false !== $cached ) {
				return $cached;
			}
		}

		return false;
	}

	/**
	 * Check whether the current request is a cart/checkout display request.
	 *
	 * @return bool True for cart, checkout, and WooCommerce Blocks Store API requests.
	 */
	private function is_cart_checkout_display_request() {
		if ( function_exists( 'is_cart' ) && is_cart() ) {
			return true;
		}

		if ( function_exists( 'is_checkout' ) && is_checkout() ) {
			return true;
		}

		if ( isset( $_SERVER['REQUEST_URI'] ) ) {
			$request_uri = esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) );
			return false !== strpos( $request_uri, '/wc/store/' );
		}

		return false;
	}

	/**
	 * Translate product name on the fly.
	 */
	public function translate_product_name( $name, $product ) {
		return $this->translate_product_property( $name, $product, 'title' );
	}

	/**
	 * Translate product short description on the fly.
	 */
	public function translate_product_short_description( $short_description, $product ) {
		return $this->translate_product_property( $short_description, $product, 'short_description' );
	}

	/**
	 * Translate product description on the fly.
	 */
	public function translate_product_description( $description, $product ) {
		return $this->translate_product_property( $description, $product, 'description' );
	}
}
