<?php
/**
 * The GTranslate class.
 *
 * Takes care of content translations for GTranslate
 * Not saving email translations as they are dynamic for each customer since the products are changing in every email message
 *
 *
 * @since      10.7
 * @package    CartBounty Pro - Save and recover abandoned carts for WooCommerce
 * @subpackage CartBounty Pro - Save and recover abandoned carts for WooCommerce/includes
 * @author     Streamline.lv
 */
class CartBounty_Pro_GTranslate{

	/**
	 * The admin handler that manages the plugin's settings, options, and backend functionality.
	 *
	 * @since    10.9
	 * @access   protected
	 * @var      CartBounty_Pro_Admin    $admin    Provides methods to control and extend the plugin's admin area.
	 */
	protected $admin = null;

	/**
	 * The API connector responsible for handling communication with external services.
	 *
	 * @since    10.9
	 * @access   protected
	 * @var      CartBounty_Pro_API_Connector    $api    Provides methods to send and receive data via API requests.
	 */
	protected $api = null;

	/**
	 * The API access credentials used to authenticate requests with the external service.
	 *
	 * @since    10.9
	 * @access   protected
	 * @var      array    $api_access    Contains authentication data such as API key, token, or other required parameters.
	 */
	protected $api_access = null;

	/**
	 * Get the admin handler (lazy-loaded).
	 * Creates the connector on first use and then reuses the same instance.
	 *
	 * @since 10.9
	 * @access protected
	 * @return CartBounty_Pro_Admin
	 */
	protected function admin(){
		
		if( $this->admin === null ){
			$this->admin = new CartBounty_Pro_Admin( CARTBOUNTY_PRO_PLUGIN_NAME_SLUG, CARTBOUNTY_PRO_VERSION_NUMBER );
		}

		return $this->admin;
	}

	/**
	 * Get the API connector (lazy-loaded).
	 * Creates the connector on first use and then reuses the same instance.
	 *
	 * @since 10.9
	 * @access protected
	 * @return CartBounty_Pro_API_Connector
	 */
	protected function api(){
		
		if( $this->api === null ){
			$this->api = new CartBounty_Pro_API_Connector();
		}

		return $this->api;
	}

	/**
	 * Get the API access creentials (lazy-loaded).
	 * Creates the connector on first use and then reuses the same instance.
	 *
	 * @since 10.9
	 * @access protected
	 * @return array
	 */
	protected function api_access(){
		
		if( $this->api_access === null ){
			$this->api_access = $this->get_api_access();
		}

		return $this->api_access;
	}

	/**
	 * Method checks if GTranslate is active
	 *
	 * @since    10.7
	 * @return   boolean
	 */
	function is_active(){
		$result = false;

		if( class_exists( 'GTranslate' ) ){
			$result = true;
		}

		return $result;
	}

	/**
	 * Method retrieves saved API credentials
	 *
	 * @since    10.9
	 * @return 	 Array
	 */
	public function get_api_access(){
		$admin = $this->admin();
		$api_access = array(
			'api_key' 	=> '',
			'api_url' 	=> 'https://api.translatex.com/translate',
		);

		$settings = $admin->get_settings( 'settings' );
		$gtranslate_key = isset( $settings['gtranslate_key'] ) ? $settings['gtranslate_key'] : '';

		if( !empty( $gtranslate_key ) ){
			$api_access['api_key'] = esc_attr( $gtranslate_key ); //Retrieve GTranslate API token from database
		}

		return $api_access;
	}

	/**
	 * Method checks if API is valid and GTranslate plugin enabled
	 *
	 * @since    10.7
	 * @return 	 boolean
	 */
	public function ready_to_translate(){
		$status = false;
		$api_access = $this->api_access();
		$api_key = $api_access['api_key'];
		$is_active = $this->is_active();

		if( !empty( $api_key ) && $is_active ){
			$status = true;
		}

		return $status;
	}

	/**
	 * Retrieve selected language by the customer using GTranslate paid version.
	 * The GTranslate free plan detects language differently and is not supported by CartBounty
	 *
	 * @since    10.7
	 * @return   string
	 */
	function get_selected_language(){
		$language = '';

		if( isset( $_SERVER['HTTP_X_GT_LANG'] ) ){
			$language = $_SERVER['HTTP_X_GT_LANG'];
		}

		return $language;
	}

	/**
	 * Handling translations
	 *
	 * @since    10.7
	 * @return   array
	 * @param    array     	$args                		Content that must be translated
	 * @param    array     	$translatable_map           Array of field paths to be translated (e.g. [ [ 'title' ], [ 'options', 'body' ] ])
	 * @param    array     	$source_language            Content that must be translated
	 * @param    array     	$target_language            Content that must be translated
	 */
	private function handle_translations( $args, $translatable_map ){

		if( $this->ready_to_translate() ){

			$api = $this->api();
			$source_language = $args['source_language'];
			$target_language = $args['target_language'];

			if( !empty( $source_language ) && !empty( $target_language ) ){

				$translatable_texts = array();
				$post_body = array();

				//Collect all texts for translation
				foreach( $translatable_map as $path ){
					$value = $args;
					
					foreach( $path as $step ){
						
						if( isset( $value[ $step ] ) ){
							$value = $value[ $step ];
						
						}else{
							$value = null;
							break;
						}
					}

					if( !empty( $value ) && is_string( $value ) ){
						$translatable_texts[] = $value;

					}else{
						$translatable_texts[] = null; // Placeholder to preserve mapping index
					}
				}

				$url_parameters = array(
					'sl' => $source_language,
					'tl' => $target_language,
				);

				$data = array(
					'text' => $translatable_texts
				);

				foreach( $data['text'] as $val ){
					$post_body[] = 'text=' . rawurlencode( $val );
				}

				$data = implode( '&', array_filter( $post_body ) );

				$result = $api->connect( 'gtranslate', $this->api_access(), http_build_query( $url_parameters ), 'POST', $data );

				if( $result['status_code'] === 200 && !empty( $result['response']->translation ) ){
					$translated = $result['response']->translation;
					$t_index = 0;

					//Remap translations back to original args
					foreach( $translatable_map as $key => $path ){
						
						if( $translatable_texts[$key] === null ){
							continue; // Skip untranslatable/null values
						}

						$ref =& $args;
						
						foreach( $path as $j => $step ){
							
							if( $j === count( $path ) - 1 ){
								$ref[$step] = $translated[$t_index++] ?? $ref[$step];

							}else{
								
								if( !isset( $ref[$step] ) || !is_array( $ref[$step] ) ){
									$ref[$step] = array();
								}
								$ref =& $ref[$step];
							}
						}
					}
				}
			}
		}

		return $args;
	}

	/**
	 * Translate email reminders
	 *
	 * @since    10.7
	 * @return   array
	 * @param    array     	$args                		Content that must be translated including additional details for the email message
	 */
	function translate_email( $args ){
		$map = array();

		//Product titles
		foreach( $args['products'] as $key => $product ){
			
			if( !empty( $product['title'] ) ){
				$map[] = array( 'products', $key, 'title' );
			}
		}

		//Text fields
		foreach( array( 'heading', 'content', 'coupon_expires_text', 'coupon_description', 'complete_checkout', 'unsubscribe', 'copyright', 'rights_reserved', 'email_subject' ) as $field ){
			
			if( !empty( $args[$field] ) ){
				$map[] = array( $field );
			}
		}

		//Store address
		foreach( array( 'address_1', 'address_2' ) as $key ){
			
			if( !empty( $args['store_address'][$key] ) ){
				$map[] = array( 'store_address', $key );
			}
		}

		return $this->handle_translations( $args, $map );
	}

	/**
	 * Translate Push notifications
	 *
	 * @since    10.7
	 * @return   array
	 * @param    array     	$args                		Content that must be translated
	 */
	function translate_push_notification( $args ){
		$map = array();

		if( !empty( $args['title'] ) ){
			$map[] = array( 'title' );
		}

		if( !empty( $args['options']['body'] ) ){
			$map[] = array( 'options', 'body' );
		}

		if( !empty( $args['options']['actions'] ) ){
			
			foreach( $args['options']['actions'] as $i => $action ){
				
				if( !empty( $action['title'] ) ){
					$map[] = array( 'options', 'actions', $i, 'title' );
				}
			}
		}

		return $this->handle_translations( $args, $map );
	}

	/**
	 * Translate BulkGate SMS text messages
	 *
	 * @since    10.7
	 * @return   array
	 * @param    array     	$args                		Content that must be translated
	 */
	function translate_bulkgate_sms( $args ){
		$map = array();

		if( !empty( $args['content'] ) ){
			$map[] = array( 'content' );
		}

		return $this->handle_translations( $args, $map );
	}
}