<?php

/**
 * ATFPP Ajax Handler
 *
 * @package ATFPP
 */

/**
 * Do not access the page directly
 */
if (! defined('ABSPATH')) {
	exit;
}

/**
 * ATFPP Helper
 */
if (! class_exists('ATFPP_Helper')) {
	class ATFPP_Helper
	{
		/**
		 * Member Variable
		 *
		 * @var instance
		 */
		private static $instance;

		/**
		 * Stores custom block data for processing and retrieval.
		 *
		 * This static array holds the data related to custom blocks that are
		 * used within the plugin. It can be utilized to manage and manipulate
		 * the custom block information as needed during AJAX requests.
		 *
		 * @var array
		 */
		private $custom_block_data_array = array();

		/**
		 * Gets an instance of our plugin.
		 *
		 * @param object $settings_obj timeline settings.
		 */
		public static function get_instance()
		{
			if (null === self::$instance) {
				self::$instance = new self();
			}
			return self::$instance;
		}

		public static function get_custom_block_post_id()
		{
			$first_post_id = null;

			$query = new WP_Query(
				array(
					'post_type'      => 'atfp_add_blocks',
					'posts_per_page' => 1,
					'orderby'        => 'date',
					'order'          => 'ASC',
				)
			);

			$existing_post = $query->posts ? $query->posts[0] : null;

			if (! $existing_post) {
				$post_title    = esc_html__('Add More Gutenberg Blocks', 'automatic-translation-for-polylang-pro');
				$first_post_id = wp_insert_post(
					array(
						'post_title'   => $post_title,
						'post_content' => '',
						'post_status'  => 'publish',
						'post_type'    => 'atfp_add_blocks',
					)
				);
			} elseif ($query->have_posts()) {
				$query->the_post();
				$first_post_id = get_the_ID();
			}

			return $first_post_id;
		}

		public function get_block_parse_rules()
		{
			$response = wp_remote_get( esc_url_raw( ATFPP_URL . 'includes/block-translation-rules/block-rules.json' ), array(
				'timeout' => 15,
			) );

			if ( is_wp_error( $response ) || 200 !== (int) wp_remote_retrieve_response_code( $response ) ) {
				global $wp_filesystem;

				// Initialize the WordPress filesystem
				if ( ! function_exists( 'WP_Filesystem' ) ) {
					require_once ABSPATH . 'wp-admin/includes/file.php';
				}

				WP_Filesystem();

				$local_path = ATFPP_DIR_PATH . 'includes/block-translation-rules/block-rules.json';
				if($wp_filesystem->exists($local_path) && $wp_filesystem->is_readable( $local_path )){
					$block_rules = $wp_filesystem->get_contents( $local_path );
				}else{
					$block_rules = array();
				}
			} else {
				$block_rules = wp_remote_retrieve_body( $response );
			}

			if(empty($block_rules)){
				return array();
			}

			$block_translation_rules = json_decode($block_rules, true);

			$this->custom_block_data_array = isset($block_translation_rules['AtfpBlockParseRules']) ? $block_translation_rules['AtfpBlockParseRules'] : null;

			$custom_block_translation = get_option('atfp_custom_block_translation', false);

			if (! empty($custom_block_translation) && is_array($custom_block_translation)) {
				foreach ($custom_block_translation as $key => $block_data) {
					$block_rules = isset($block_translation_rules['AtfpBlockParseRules'][$key]) ? $block_translation_rules['AtfpBlockParseRules'][$key] : null;
					$this->filter_custom_block_rules(array($key), $block_data, $block_rules);
				}
			}

			$block_translation_rules['AtfpBlockParseRules'] = $this->custom_block_data_array ? $this->custom_block_data_array : array();

			return $block_translation_rules;
		}

		private function filter_custom_block_rules(array $id_keys, $value, $block_rules, $attr_key = false)
		{
			$block_rules = is_object($block_rules) ? json_decode(json_encode($block_rules)) : $block_rules;

			if (! isset($block_rules)) {
				return $this->merge_nested_attribute($id_keys, $value);
			}
			if (is_object($value) && isset($block_rules)) {
				foreach ($value as $key => $item) {
					if (isset($block_rules[$key]) && is_object($item)) {
						$this->filter_custom_block_rules(array_merge($id_keys, array($key)), $item, $block_rules[$key], false);
						continue;
					} elseif (! isset($block_rules[$key]) && true === $item) {
						$this->merge_nested_attribute(array_merge($id_keys, array($key)), true);
						continue;
					} elseif (! isset($block_rules[$key]) && is_object($item)) {
						$this->merge_nested_attribute(array_merge($id_keys, array($key)), $item);
						continue;
					}
				}
			}
		}

		private function merge_nested_attribute(array $id_keys, $value)
		{
			$value = is_object($value) ? json_decode(json_encode($value), true) : $value;

			$current_array = &$this->custom_block_data_array;

			foreach ($id_keys as $index => $id) {
				if (! isset($current_array[$id])) {
					$current_array[$id] = array();
				}
				$current_array = &$current_array[$id];
			}

			$current_array = $value;
		}

		public static function replace_links_with_translations($content, $locale, $current_locale)
		{
			// Get all URLs in the content that start with the current home page URL (current domain), regardless of attribute or tag
			$home_url = preg_quote(get_home_url(), '/');
			$pattern = '/(' . $home_url . '[^\s"\'<>]*)/i';
			$terms_data=self::get_terms_data();

			if (preg_match_all($pattern, $content, $matches)) {
				$image_urls=self::get_image_ids_by_urls($matches[1], $locale);

				$content = preg_replace_callback($pattern, function ($match) use ($image_urls, $locale, $current_locale, $terms_data) {
		
					$href = $match[1];
		
					if (preg_match('/<img[^>]+(src|srcset)=[\'"][^\'"]*' . preg_quote($href, '/') . '[\'"][^>]*>/i', $match[0])) {
						return $href;
					}
		
					if (isset($image_urls[$href]) && !empty($image_urls[$href])) {
						return $image_urls[$href];
					}
		
					$postID = url_to_postid($href);
					if ($postID > 0) {
						$translatedPost = pll_get_post($postID, $locale);
						if ($translatedPost) {
							$link = get_permalink($translatedPost);
							if ($link) {
								return esc_url(urldecode_deep($link));
							}
						}
					}

					$path = trim(str_replace(pll_home_url($current_locale), '', $href), '/');
					$category_slug = end(array_filter(explode('/', $path)));
		
					$taxonomy_name = self::extract_taxonomy_name($path, $terms_data);
					$taxonomy_name = $taxonomy_name ? $taxonomy_name : 'category';
		
					$category = get_term_by('slug', $category_slug, $taxonomy_name);
		
					if (!$category) {
						// Remove the language prefix if using Polylang
						$languages = pll_languages_list(); // e.g., ['en', 'fr']
						$segments = explode('/', $path);
						if (in_array($segments[0], $languages)) {
							$lang_code = $segments[0];
							$category_id = Pll()->model->term_exists_by_slug($category_slug, $lang_code, $taxonomy_name);

							if ($category_id) {
								$category = get_term($category_id, $taxonomy_name);
							}
						}
					}
		
					if ($category) {
						$term_id = pll_get_term($category->term_id, $locale);
						if ($term_id > 0) {
							$link = get_category_link($term_id);
							return esc_url($link);

						}
					}
					return $href;
		
				}, $content);
			}

			return $content;
		}

		private static function extract_taxonomy_name($path, $terms_data){
			// Remove the language prefix if using Polylang
			$languages = pll_languages_list(); // e.g., ['en', 'fr']
			$segments = explode('/', $path);
			if (in_array($segments[0], $languages)) {
				array_shift($segments); // remove 'en', 'fr', etc.
			}
			
			if (empty($segments)) {
				return null;
			}

			// First segment after language is usually the taxonomy slug
			$possible_tax = $segments[0];

			if (taxonomy_exists($possible_tax) || (isset($terms_data[$possible_tax]) && taxonomy_exists($terms_data[$possible_tax]))) {
		   		return isset($terms_data[$possible_tax]) ? $terms_data[$possible_tax] : $possible_tax;
			}

			return false;
		}

		private static function get_terms_data(){
			$taxonomies=get_taxonomies([],'objects');

			$taxonomies_data=array();
			foreach($taxonomies as $key=>$taxonomy){
				if(isset($taxonomy->rewrite['slug'])){
					$taxonomies_data[$taxonomy->rewrite['slug']]=$key;
				}else{
					$taxonomies_data[$key]=$key;
				}
			}

			return $taxonomies_data;
		}

		private static function get_image_ids_by_urls( $image_urls = [] , $locale='en') {
			global $wpdb;
		
			// Convert single URL string to array
			if ( is_string( $image_urls ) ) {
				$image_urls = [ $image_urls ];
			}
		
			if ( empty( $image_urls ) || ! is_array( $image_urls ) ) {
				return [];
			}
		
			$upload_dir = wp_upload_dir();
			$base_url   = $upload_dir['baseurl'];
			$results    = [];
		
			$cleaned_paths_map = []; // [cleaned_path] => [original_urls]
		
			foreach ( $image_urls as $url ) {
				if ( strpos( $url, $base_url ) === false ) {
					$results[ $url ] = false;
					continue;
				}
		
				// Relative path
				$relative_path = str_replace( $base_url . '/', '', $url );
		
				// Strip size suffix if present
				$cleaned_path = preg_replace( '/-\d+x\d+(?=\.(jpg|jpeg|png|gif|webp)$)/i', '', $relative_path );
		
				// Map cleaned path to original URL(s)
				if ( ! isset( $cleaned_paths_map[ $cleaned_path ] ) ) {
					$cleaned_paths_map[ $cleaned_path ] = [];
				}
		
				$cleaned_paths_map[ $cleaned_path ][] = $url;
			}

			$like_parts = [];
			$args       = [];

			// Build the OR'ed LIKEs and gather args
			foreach ( array_keys( $cleaned_paths_map ) as $path ) {
				$like_parts[] = 'guid LIKE %s';
				// Always escape for LIKE, then add wildcards yourself
				$args[] = '%' . $wpdb->esc_like( $path ) . '%';
			}

			// Nothing to search? bail early.
			if ( empty( $like_parts ) ) {
				return $results;
			}

			// Compose the SQL with placeholders only
			$sql = "
				SELECT ID, guid
				FROM {$wpdb->posts}
				WHERE post_type = %s
				AND (" . implode( ' OR ', $like_parts ) . ")
			";

			// First arg is for post_type, then all the LIKE args
			array_unshift( $args, 'attachment' );

			// Prepare once with all arguments (wpdb::prepare accepts an array)
			$prepared = $wpdb->prepare( $sql, $args );

			// Run the query
			$found = $wpdb->get_results( $prepared );

		
			// Map found GUIDs to IDs
			$guid_to_id = [];
			foreach ( $found as $row ) {
				
				$guid_to_id[ $row->guid ] = esc_url($row->guid);
				$translated_post=pll_get_post(intval($row->ID), $locale);

				if($translated_post){
					$image_url=wp_get_attachment_url(intval($translated_post));

					if($image_url && !empty($image_url)){
						$guid_to_id[$row->guid]=esc_url($image_url);
					}
				}
			}
		
			// Match original URLs to found IDs
			foreach ( $image_urls as $original_url ) {
				$found_id = false;
		
				if(isset($guid_to_id[$original_url])){
					$results[$original_url]=$guid_to_id[$original_url];
					continue;
				}

				// Exact match first
				if ( isset( $guid_to_id[ $original_url ] ) ) {
					$found_id = $guid_to_id[ $original_url ];
				} else {
					// Fallback to cleaned path match
					$relative_path = str_replace( $base_url . '/', '', $original_url );
					$cleaned_path  = preg_replace('/-\d+x\d+(?=\.(jpg|jpeg|png|gif|webp)$)/i', '', $relative_path );

					preg_match('/-\d+x\d+(?=\.(jpg|jpeg|png|gif|webp)$)/i', $original_url, $matches);
					$suffix = isset($matches[0]) ? $matches[0] : '';

					foreach ( $guid_to_id as $guid => $url ) {
						if ( strpos( $guid, $cleaned_path ) !== false ) {
							if (!empty($suffix)) {
								// Insert $suffix before the file extension in $url
								$found_id = preg_replace('/(\.[a-zA-Z0-9]+)$/', $suffix . '$1', $url);
							} else {
								$found_id = $url;
							}
							break;
						}
					}
				}
		
				$results[ $original_url ] = esc_url($found_id);
			}
			
		
			return $results;
		}

		public static function translation_data_migration(){
			$already_migrated = get_option('atfp_translation_string_migration', false);

			if(!$already_migrated){
				
				$old_data=get_option('cpt_dashboard_data', array());

				$updated=array();

				if(isset($old_data['atfp']) && count($old_data['atfp']) > 0){
					foreach($old_data['atfp'] as $data){
						$updated_data=$data;
						if(isset($data['string_count'])){
							$updated_data['word_count']=$data['string_count'];
							$updated_data['string_count']=$data['string_count'] / 30;
						}

						if(isset($data['source_string_count'])){
							$updated_data['source_word_count']=$data['source_string_count'];
							$updated_data['source_string_count']=$data['source_string_count'] / 30;
						}

						$updated[]=$updated_data;
					}

					if(count($updated) > 0){
						$old_data['atfp']=$updated;

						update_option('cpt_dashboard_data', $old_data);
					}
				}

				update_option('atfp_translation_string_migration', true);
			}
		}

		public static function get_custom_fields_data(){
			$result=self::get_custom_fields_query();

			$data=array();

			if($result && is_array($result)){
				$excluded_fields=self::get_excluded_custom_fields_keys();
				$allowed_fields=self::get_allowed_custom_fields();

				foreach($result as $result){
					if(in_array($result['meta_key'], $excluded_fields)){
						continue;
					}

					$serialized_value=maybe_unserialize($result['meta_value']);
					$value_type=json_decode($result['meta_value'], true) ? 'array' : (is_array($serialized_value) ? 'array' : 'string');
					
					$type=isset($allowed_fields[$result['meta_key']]) && true === $allowed_fields[$result['meta_key']]['status'] ? $allowed_fields[$result['meta_key']]['type'] : $value_type;
					
					$status=isset($allowed_fields[$result['meta_key']]) && true === $allowed_fields[$result['meta_key']]['status'] ? 'Supported' : 'Unsupported';

					$data[sanitize_text_field($result['meta_key'])]=['type'=>$type, 'status'=>$status];
				}
			}

			$default_allowed_fields=self::get_default_allowed_fields();

			$default_key_diff=array_diff(array_keys($default_allowed_fields), array_keys($data));

			foreach($default_key_diff as $key){
				$status='Supported';
				$saved_allowed_fields=get_option('atfp_allowed_custom_fields', false);
				$status=isset($saved_allowed_fields[$key]) && true === $saved_allowed_fields[$key]['status'] ? 'Supported' : 'Unsupported';

				$data[$key]=['type'=>$default_allowed_fields[$key]['type'], 'status'=>$status];
			}

			$data=apply_filters('atfp/custom_fields/all_fields', $data);

			return $data;
		}

		private static function get_custom_fields_query(){
			global $wpdb;

             // Escape LIKE pattern for system meta (_%)
			 $like_pattern = $wpdb->esc_like('_') . '%';

			// SQL with DISTINCT + filtering
			$sql = $wpdb->prepare(
				"
				SELECT DISTINCT pm.meta_key, pm.meta_value
				FROM {$wpdb->postmeta} pm
				WHERE pm.meta_key NOT LIKE %s
				AND pm.meta_value <> ''                         -- skip empty
				AND pm.meta_value NOT IN ('0','1')              -- skip boolean
				AND pm.meta_value NOT REGEXP '^[0-9]+$'         -- skip integer
				AND pm.meta_value NOT REGEXP '^[0-9]+\\.[0-9]+$' -- skip decimal
				AND pm.meta_value NOT REGEXP '^(https?:\/\/|www\.)[A-Za-z0-9\.\-]+.*$' -- skip URLs
				ORDER BY pm.meta_key ASC
				",
				$like_pattern
			);

            // Get results
            $results = $wpdb->get_results($sql, ARRAY_A);

			return $results;
		}

		private static function get_excluded_custom_fields_keys(){
			$excluded_fields= array(
                '_edit_last',
                '_edit_lock',
                '_wp_page_template',
                '_wp_attachment_metadata',
                '_icl_translator_note',
                '_alp_processed',
                '_pingme',
                '_encloseme',
                '_icl_lang_duplicate_of',
                'atfpp_parent_post_language',
                'atfp_parent_post_language_slug',
                'atfpp_parent_post_language_slug',
                'twae_exists',
                'twae_post_migration',
                'twae_style_migration',
                '_thumbnail_id',
            );

            return apply_filters('atfp/custom_fields/excluded_keys', $excluded_fields);
		}

		public static function get_allowed_custom_fields(){
			$allowed_custom_fields=self::get_allowed_custom_fields_data();
			$allowed_custom_fields=apply_filters('atfp/custom_fields/allowed_fields', $allowed_custom_fields);
		
			return $allowed_custom_fields;
		}

		private static function get_allowed_custom_fields_data(){			
			$allowed_fields=get_option('atfp_allowed_custom_fields', false);

			if($allowed_fields && is_array($allowed_fields) && count($allowed_fields) > 0){
				return $allowed_fields;
			}

			if(!$allowed_fields || !is_array($allowed_fields)){
				$default_allowed_fields=self::get_default_allowed_fields();

				foreach($default_allowed_fields as $key => $value){
					$allowed_fields[$key]=['status'=>true, 'type'=>'string'];
				}

				update_option('atfp_allowed_custom_fields', $allowed_fields);
			}

			ksort($allowed_fields);
			
			return $allowed_fields;
		}

		private static function get_default_allowed_fields(){
			$found=false;

			$response = wp_remote_get( esc_url_raw( ATFPP_URL . 'includes/block-translation-rules/default-allow-metafields.json' ), array(
				'timeout' => 15,
			) );

			if ( is_wp_error( $response ) || 200 !== (int) wp_remote_retrieve_response_code( $response ) ) {
				global $wp_filesystem;

				// Initialize the WordPress filesystem
				if ( ! function_exists( 'WP_Filesystem' ) ) {
					require_once ABSPATH . 'wp-admin/includes/file.php';
				}

				WP_Filesystem();

				$local_path = ATFPP_DIR_PATH . 'includes/block-translation-rules/default-allow-metafields.json';
				if($wp_filesystem->exists($local_path) && $wp_filesystem->is_readable( $local_path )){
					$found=true;
					$default_allowed_fields = $wp_filesystem->get_contents( $local_path );
				}
			}else{
				$found=true;
				$default_allowed_fields = wp_remote_retrieve_body( $response );
			}

			if(!$found){
				return array();
			}

			return json_decode($default_allowed_fields, true)	;
		}

		public static function bulk_translation_render($current_screen){
			global $polylang;
        
			if(!$polylang || !property_exists($polylang, 'model')){
				return false;
			}

			$translated_post_types = $polylang->model->get_translated_post_types();
			$translated_taxonomies = $polylang->model->get_translated_taxonomies();
	
			$translated_post_types = array_values($translated_post_types);
			$translated_taxonomies = array_values($translated_taxonomies);
				
			$translated_post_types=array_filter($translated_post_types, function($post_type){
				return is_string($post_type);
			});
	
			$translated_taxonomies=array_filter($translated_taxonomies, function($taxonomy){
				return is_string($taxonomy);
			});
	
			$valid_post_type=(isset($current_screen->post_type) && !empty($current_screen->post_type)) && in_array($current_screen->post_type, $translated_post_types) && $current_screen->post_type !== 'attachment' ? $current_screen->post_type : false;
			$valid_taxonomy=(isset($current_screen->taxonomy) && !empty($current_screen->taxonomy)) && in_array($current_screen->taxonomy, $translated_taxonomies) ? $current_screen->taxonomy : false;
	
			if((!$valid_post_type && !$valid_taxonomy) || ((!$valid_post_type || empty($valid_post_type)) && !isset($valid_taxonomy)) || (isset($current_screen->taxonomy) && !empty($current_screen->taxonomy) && !$valid_taxonomy)){
				return false;
			}

			return true;
		}
	}
}
