<?php

if ( ! class_exists( 'DocswriteAPI' ) ) {
	class DocswriteAPI {
		/**
		 * Map of command names to static methods.
		 *
		 * @var array
		 */
		private static $method_map = [
			'connect'                => 'connect',
			'publish_posts'          => 'publish_posts',
	
			'disconnect'             => 'disconnect',
			'update_posts'           => 'update_posts',
			'delete_posts'           => 'delete_posts',
			'get_authors'            => 'get_authors',
			'get_taxonomies_terms'   => 'get_taxonomies_terms',
			'get_categories'         => 'get_categories',
			'get_tags'               => 'get_tags',
			'check_connection_status'=> 'check_connection_status',
		];
	
		/**
		 * @return void
		 */
		public static function register_api_endpoints() {
			// Add the endpoint trigger for non-logged in users
			add_action( 'wp_ajax_nopriv_docswrite', array( 'DocswriteAPI', 'execute' ) );
		}

		/**
		 * Execute the request. This structure is very easy to extend - just add new methods in the class, nothing more.
		 *
		 * @return void
		 */
		public static function execute() {
			// Ensure REQUEST_METHOD is set before accessing it
			$request_method = isset($_SERVER['REQUEST_METHOD']) ? sanitize_text_field($_SERVER['REQUEST_METHOD']) : '';

			// Check if the request is POST
			if ($request_method !== 'POST') {
				wp_send_json_error([
					'message' => 'Invalid request method. Only POST allowed.'
				], 405);
				wp_die();
			}
			// Check if the request is POST
			if ( $_SERVER['REQUEST_METHOD'] !== 'POST' ) {
				wp_send_json_error( [
					'message' => 'Invalid request method. Only POST allowed.'
				], 405 );
				wp_die();
			}

			// Decode the input from JSON
			$json    = file_get_contents( 'php://input' );
			$request = json_decode( $json, true );

			// Validate JSON and check required fields
			if (json_last_error() !== JSON_ERROR_NONE) {
				wp_send_json_error([
					'message' => 'Invalid JSON format.'
				], 400);
				wp_die();
			}

			// Ensure the 'action' element is set and 'data' is an array.
			if ( isset( $request['command'] ) && is_array( $request['data'] ) ) {
				// Checking security - for correct UUID
				if ( $request['command'] != 'connect' && ! self::check_uuid( $request['data'] ) ) {
					wp_send_json_error( [
						'message' => 'Wrong UUID or manually disconnected'
					] );
					wp_die();
				}

				$action = $request['command'];
				$data   = $request['data'];
				
				switch ($action) {
					case 'connect':
						self::connect($data);
						break;
					case 'publish_posts':
						self::publish_posts($data);
						break;
					case 'disconnect':
						self::disconnect($data);
						break;
					case 'update_posts':
						self::update_posts($data);
						break;
					case 'delete_posts':
						self::delete_posts($data);
						break;
					case 'get_authors':
						self::get_authors($data);
						break;
					case 'get_taxonomies_terms':
						self::get_taxonomies_terms($data);
						break;
					case 'get_categories':
						self::get_categories($data);
						break;
					case 'get_tags':
						self::get_tags($data);
						break;
					case 'check_connection_status':
						self::check_connection_status($data);
						break;
					default:
						wp_send_json_error([
							'message' => 'Invalid command.'
						], 400);
						break;
				}
			}
			
			wp_die();

		}

		/**
		 * Check every request for correct UUID
		 *
		 * @param $request_data
		 *
		 * @return bool
		 */
		public static function check_uuid( $request_data ) {
			if ( Docswrite::is_connected() && isset( $request_data['uuid'] ) && $request_data['uuid'] && $request_data['uuid'] === Docswrite::get_website_id() ) {
				return true;
			}

			return false;
		}

		/**
		 * Connecting that ID?
		 * */
		public static function connect( $request_data ) {
			if ( isset( $request_data['uuid'] ) && $request_data['uuid'] && $request_data['uuid'] == Docswrite::get_website_id() ) {
				if ( update_option( Docswrite::DOCSWRITE_CONNECTION_OPTION, $request_data['uuid'] ) ) {
					wp_send_json_success( [
						'message' => 'Connected successfully'
					] );
				} else {
					wp_send_json_error( [
						'message' => 'Already connected'
					] );
				}
				wp_die();
			}
		}

		/**
		 * Status that connection
		 * @return void
		 * */
		public static function check_connection_status() {
			$status = ((bool) get_option( Docswrite::DOCSWRITE_CONNECTION_OPTION )) ? 'Connected' : 'Disconnected';

			wp_send_json_success( [
				'message' => $status
			] );
		
			wp_die();
		}

		/**
		 * Handles disconnection request from the user.
		 *
		 * @return void
		 */
		public static function disconnect() {
			update_option( Docswrite::DOCSWRITE_CONNECTION_OPTION, 0 );
			wp_send_json_success( [
				'message' => 'successfully disconnected'
			] );

			wp_die();
		}

		/**
		 * Search post by Docswrite::DOCSWRITE_POST_ID_META_KEY
		 *
		 * @param $docswrite_id
		 *
		 * @return int[]|WP_Post[]|null
		 */
		public static function get_post_by_docswrite_id( $docswrite_id ) {
			$docswrite_id = intval($docswrite_id);

			if ($docswrite_id <= 0) {
				return [];
			}
		
			// Query for posts with the given meta key and value
			$posts = get_posts(array(
				'meta_key'   => Docswrite::DOCSWRITE_POST_ID_META_KEY,
				'meta_value' => $docswrite_id,
				'post_type'  => 'any',
				'numberposts' => -1,
				'post_status' => 'any',
			));
		
			// If no posts found, return an empty array
			if (empty($posts)) {
				return [];
			}
		
			return $posts;
		}

		/**
		 * Publishes multiple posts.
		 *
		 * @param array $request_data The data containing the posts to be published.
		 *
		 * @return void
		 */
		public static function publish_posts( $request_data ) {
			if ( ! is_array( $request_data['posts'] ) || ! $request_data['posts'] ) {
				wp_send_json_error( [ 'message' => 'No posts in request' ] );
				wp_die();
			}
			$posts_published  = 0;
			$posts_permalinks = [];

			foreach ( $request_data['posts'] as $post_data ) {
				// Prepare post data
				$new_post = array(
					'post_title'    => sanitize_text_field( $post_data['title'] ),
					'post_name'     => sanitize_title_with_dashes( $post_data['slug'] ), // For slugs, this must be activated: https://icecream.me/864fbcf145c46b76999bc36548e29bfa
					'tags_input'    => $post_data['tags'],
					'post_status'   => sanitize_text_field( $post_data['state'] ),
					'post_author'   => (int) (isset($post_data['author']) ? $post_data['author'] : 1), // it must be an INT
					'post_date'     => gmdate( 'Y-m-d H:i:s', strtotime( $post_data['date'] ) ),
					'post_excerpt'  => sanitize_text_field( $post_data['excerpt'] ),
					'post_type'     => sanitize_text_field( $post_data['post_type'] ),
					'post_category' => $post_data['categories'],
					'post_content'  => wp_kses_post( $post_data['content'] ),
				);
				
				// Process content for images
				$dom = new DOMDocument();
				@$dom->loadHTML(mb_convert_encoding($new_post['post_content'], 'HTML-ENTITIES', 'UTF-8'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
				
				$images = $dom->getElementsByTagName('img');
				
				foreach ($images as $img) {
					$src = $img->getAttribute('src');
					$alt = $img->getAttribute('alt');
					$title = $img->getAttribute('title');
					
	
					if (filter_var($src, FILTER_VALIDATE_URL)) {
						
						$upload_result = self::upload_image_from_url($src, array(
							'alt_text' => $alt,
							'caption' => $title
						));

						if (!is_wp_error($upload_result)) {
							$img->setAttribute('src', $upload_result['url']);
							if ($upload_result['alt']) {
								$img->setAttribute('alt', $upload_result['alt']);
							}
						}
					} 
				}

				$new_post['post_content'] = $dom->saveHTML();
				
				
				// Insert post into database
				$post_id = wp_insert_post( $new_post, $wp_error=true );
				if (is_wp_error($post_id)) {
					$error_message = $post_id->get_error_message();
					error_log( 'Post insertion failed: ' . $error_message );
					echo 'Error: ' . $error_message;
				}
				if ( $post_id && !is_wp_error($post_id) ) {
					update_post_meta( $post_id, Docswrite::DOCSWRITE_POST_ID_META_KEY, $post_id );
					update_post_meta( $post_id, Docswrite::DOCSWRITE_POST_RAW_META_KEY, $post_data );
										
					if (isset($post_data['featured_image_url'])) {
						$featured_image_url = $post_data['featured_image_url'];
						$featured_image_alt_text = isset($post_data['featured_image_alt_text']) ? $post_data['featured_image_alt_text'] : '';
						$featured_image_caption = isset($post_data['featured_image_caption']) ? $post_data['featured_image_caption'] : '';
						self::set_image_to_post( $featured_image_url, $post_id, $featured_image_alt_text, $featured_image_caption );
					}

					// Set post metadata
					if ( isset($post_data['yoast_settings'])) {
						$post_data['yoast_settings_clean'] = [];
						foreach ( $post_data['yoast_settings'] as $tmp_key => $tmp_value ) {
							// Transform 'yoast_wpseo_*' to '_yoast_wpseo_*'
							$clean_key = str_replace( 'yoast_', '_yoast_', $tmp_key );
							$post_data['yoast_settings_clean'][ $clean_key ] = $tmp_value;
						}
						self::setup_metadata( '', $post_data['yoast_settings_clean'], $post_id );
						self::setup_yoast_social_image_ids( $post_id );
					}

					if ( isset($post_data['rankmath_settings'])) {
						self::setup_metadata( '', $post_data['rankmath_settings'], $post_id );
					}
					if ( isset($post_data['newspack_settings']) ) {
						self::setup_metadata( '', $post_data['newspack_settings'], $post_id );
					}
					// Add ACF fields support
					if ( isset($post_data['acf']) ) {
						self::setup_acf_fields( $post_data['acf'], $post_id );
					}

					// Add permalink for $post_id to $posts_permalinks[]
					$posts_permalinks[ $post_id ] = get_permalink( $post_id );
					$posts_published ++;
				}
			}

			if ( $posts_published ) {
				wp_send_json_success( [
					'message'          => 'Posts published: ' . $posts_published,
					'posts_permalinks' => $posts_permalinks,
				] );
			} else {
				wp_send_json_error( [
					'message' => 'No posts updated'
				] );
			}

			wp_die();
		}

		/**
		 * Set categories and create if they don't exist
		 *
		 * @param string $categories_string The string containing comma-separated category names.
		 *
		 * @return array The array of category IDs.
		 */
		public static function setup_categories( $categories_string ) {
			$categories_array = explode( ',', $categories_string );
			$categories_ids   = [];

			foreach ( $categories_array as $category_name ) {
				$category_id = get_cat_ID( $category_name );
				if ( $category_id == 0 ) {
					$new_category_id  = wp_create_category( $category_name );
					$categories_ids[] = $new_category_id;
				} else {
					$categories_ids[] = $category_id;
				}
			}

			return $categories_ids;
		}

		/**
		 * Donwload and set image to post
		 *
		 * @param $url
		 * @param $post_id
		 * @param $featured_image_alt_text
		 * @param $featured_image_caption
		 *
		 * @return void
		 */
		public static function set_image_to_post( $url, $post_id, $featured_image_alt_text, $featured_image_caption ) {
			require_once( ABSPATH . 'wp-admin/includes/media.php' );
			require_once( ABSPATH . 'wp-admin/includes/file.php' );
			require_once( ABSPATH . 'wp-admin/includes/image.php' );
		
			$cleaned_url = $url . '#?ext=.png';

			try {
				$featured_image_id = media_sideload_image( $cleaned_url, $post_id, '', 'id' );
			} catch (Exception $e) {
				var_dump("Error: " . $e->getMessage());
				return false;
			}
		
			if ( is_wp_error( $featured_image_id ) ) {
				var_dump( 'Featured image upload failed: ' . $featured_image_id->get_error_message() );
				return false;
			}

			set_post_thumbnail( $post_id, $featured_image_id );

			$featured_image_post = array(
				'ID'           => $featured_image_id,
				'post_title'   => sanitize_text_field( $featured_image_caption ),
				'post_excerpt' => sanitize_text_field( $featured_image_caption ),
			);
			wp_update_post( $featured_image_post );

			update_post_meta( $featured_image_id, '_wp_attachment_image_alt', sanitize_text_field( $featured_image_alt_text ) );
			
			return $featured_image_id;
		}

		/**
		 * Sets up metadata for a given post.
		 *
		 * @param string $metadata_prefix The prefix to prepend to each metadata key.
		 * @param array $metadata_array The array of metadata to set.
		 * @param integer $post_id The ID of the post to set metadata for.
		 *
		 * @return void
		 */
		public static function setup_metadata( $metadata_prefix, $metadata_array, $post_id ) {
			foreach ( $metadata_array as $key => $value ) {
				update_post_meta( $post_id, $metadata_prefix . $key, $value );
			}
		}

		/**
		 * Resolve the attachment ID for a Yoast social image URL stored on a post.
		 *
		 * Reuses the featured image attachment when the URL matches; otherwise
		 * sideloads the image into the media library. Yoast renders Open Graph
		 * and Twitter cards from the *-image-id meta, so without an ID the
		 * <meta> tag is emitted but structured data falls back to defaults.
		 *
		 * @param int $post_id
		 *
		 * @return void
		 */
		public static function setup_yoast_social_image_ids( $post_id ) {
			$image_meta_keys = [
				'_yoast_wpseo_opengraph-image' => '_yoast_wpseo_opengraph-image-id',
				'_yoast_wpseo_twitter-image'   => '_yoast_wpseo_twitter-image-id',
			];

			$thumbnail_id  = get_post_thumbnail_id( $post_id );
			$thumbnail_url = $thumbnail_id ? wp_get_attachment_url( $thumbnail_id ) : '';

			require_once( ABSPATH . 'wp-admin/includes/media.php' );
			require_once( ABSPATH . 'wp-admin/includes/file.php' );
			require_once( ABSPATH . 'wp-admin/includes/image.php' );

			foreach ( $image_meta_keys as $url_key => $id_key ) {
				$url = get_post_meta( $post_id, $url_key, true );
				if ( empty( $url ) ) {
					continue;
				}

				if ( $thumbnail_id && $thumbnail_url && $url === $thumbnail_url ) {
					update_post_meta( $post_id, $id_key, $thumbnail_id );
					continue;
				}

				try {
					$attachment_id = media_sideload_image( $url . '#?ext=.png', $post_id, '', 'id' );
				} catch ( Exception $e ) {
					error_log( 'Yoast social image sideload failed: ' . $e->getMessage() );
					continue;
				}

				if ( is_wp_error( $attachment_id ) ) {
					error_log( 'Yoast social image sideload failed: ' . $attachment_id->get_error_message() );
					continue;
				}

				update_post_meta( $post_id, $id_key, $attachment_id );
			}
		}

		/**
		 * Update post with the specified post data
		 *
		 * @param array $post_data The post data to update the post with
		 *
		 * @return void
		 */
		public static function update_posts( $request_data ) {
			if ( ! is_array( $request_data['posts'] ) || ! $request_data['posts'] ) {
				wp_send_json_error( [ 'message' => 'No posts in request' ] );
				wp_die();
			}
			$posts_updated    = 0;
			$posts_permalinks = [];

			foreach ( $request_data['posts'] as $post_data ) {
				$existing_posts = self::get_post_by_docswrite_id( $post_data['id'] );
				
				foreach ( $existing_posts as $existing_post ) {					
						$post_id = $existing_post->ID;

						wp_update_post( array(
							'ID'            => $post_id,
							'tags_input'    => $post_data['tags'],
							'post_title'    => sanitize_text_field( $post_data['title'] ),
							'post_name'     => sanitize_title_with_dashes( $post_data['slug'] ),
							'post_status'   => sanitize_text_field( $post_data['state'] ),
							'post_author'   => (int) $post_data['author'], // it must be an INT
							'post_date'     => gmdate( 'Y-m-d H:i:s', strtotime( $post_data['date'] ) ),
							'post_excerpt'  => sanitize_text_field( $post_data['excerpt'] ),
							'post_type'     => sanitize_text_field( $post_data['post_type'] ),
							'post_category' => $post_data['categories'],
							'post_content'  => wp_kses_post( $post_data['content'] ),
						) );

						update_post_meta( $post_id, Docswrite::DOCSWRITE_POST_RAW_META_KEY, $post_data );
						
						if (isset($post_data['featured_image_url'])) {
							$featured_image_url = $post_data['featured_image_url'];
							$featured_image_alt_text = isset($post_data['featured_image_alt_text']) ? $post_data['featured_image_alt_text'] : '';
							$featured_image_caption = isset($post_data['featured_image_caption']) ? $post_data['featured_image_caption'] : '';
							self::set_image_to_post( $featured_image_url, $post_id, $featured_image_alt_text, $featured_image_caption );
						}
						
						if ( isset($post_data['yoast_settings'])) {
							$post_data['yoast_settings_clean'] = [];
							foreach ( $post_data['yoast_settings'] as $tmp_key => $tmp_value ) {
								// Transform 'yoast_wpseo_*' to '_yoast_wpseo_*'
								$clean_key = str_replace( 'yoast_', '_yoast_', $tmp_key );
								$post_data['yoast_settings_clean'][ $clean_key ] = $tmp_value;
							}
							self::setup_metadata( '', $post_data['yoast_settings_clean'], $post_id );
							self::setup_yoast_social_image_ids( $post_id );
						}
						if ( isset($post_data['rankmath_settings'])) {
							self::setup_metadata( '', $post_data['rankmath_settings'], $post_id );
						}
						if ( isset($post_data['newspack_settings']) ) {
							self::setup_metadata( '', $post_data['newspack_settings'], $post_id );
						}
						// Add ACF fields support
						if ( isset($post_data['acf'])) {
							self::setup_acf_fields( $post_data['acf'], $post_id );
						}
						// Add permalink for $post_id to $posts_permalinks[]
						$posts_permalinks[ $post_id ] = get_permalink( $post_id );
						$posts_updated ++;
				}
			}

			if ( $posts_updated ) {
				wp_send_json_success( [
					'message'          => 'Posts updated: ' . $posts_updated,
					'posts_permalinks' => $posts_permalinks,
				] );
			} else {
				wp_send_json_error( [
					'message' => 'No posts updated'
				] );
			}

			wp_die();
		}

		/**
		 * Deletes posts based on the given request data
		 *
		 * @param array $request_data The request data containing the posts to delete
		 *
		 * @return void
		 */
		public static function delete_posts($request_data) {			
			if (!isset($request_data['posts']) || !is_array($request_data['posts'])) {
				wp_send_json_error([
					'message' => 'No posts provided'
				]);
				wp_die();
			}

			$deleted_posts = [];
			$failed_posts = [];
			$protected_images = [];

			foreach ($request_data['posts'] as $post) {
				if (!isset($post['id'])) {
					continue;
				}
				
				$post_id = $post['id'];

				// Get all attached media
				$attachments = get_attached_media('', $post_id);
				
				// Get featured image ID if exists
				$thumbnail_id = get_post_thumbnail_id($post_id);
				if ($thumbnail_id) {
					$attachments[$thumbnail_id] = get_post($thumbnail_id);
				}
				
				// Delete attachments safely
				foreach ($attachments as $attachment) {
					
					// Skip if it's a protected image (like logo)
					if (self::is_protected_image($attachment->ID)) {
						$protected_images[] = $attachment->ID;
						continue;
					}
		
					// Check if image is used in other posts
					if (!self::is_image_used_elsewhere($attachment->ID, $post_id)) {
						wp_delete_attachment($attachment->ID, true);
					}
				}
		
				// Delete the post
				$result = wp_delete_post($post_id, true);
		
				if ($result) {
					$deleted_posts[] = $post_id;
				} else {
					$failed_posts[] = $post_id;
				}
			}
		
			$response = [
				'message' => empty($failed_posts) ? 'Posts deleted successfully' : 'Some posts failed to delete',
				'deleted_posts' => $deleted_posts,
				'failed_posts' => $failed_posts
			];
		
			if (!empty($protected_images)) {
				$response['protected_images'] = $protected_images;
			}
					
			if (empty($failed_posts)) {
				wp_send_json_success($response);
			} else {
				wp_send_json_error($response);
			}
		
			wp_die();
		}
		
		/**
		 * Check if an image is protected (like site logo)
		 */
		private static function is_protected_image($attachment_id) {
			// Get the site logo ID
			$custom_logo_id = get_theme_mod('custom_logo');
			
			// Add other critical image IDs here
			$protected_ids = array(
				$custom_logo_id
				// Add other protected image IDs
			);
		
			return in_array($attachment_id, $protected_ids);
		}
		
		/**
		 * Check if an image is used in other posts
		 */
		private static function is_image_used_elsewhere($attachment_id, $current_post_id) {
			global $wpdb;
		
			// Check posts content
			$used_in_content = $wpdb->get_var($wpdb->prepare(
				"SELECT COUNT(*) FROM $wpdb->posts 
				WHERE ID != %d 
				AND post_status = 'publish' 
				AND (
					post_content LIKE %s 
					OR post_content LIKE %s
				)",
				$current_post_id,
				'%' . $wpdb->esc_like(wp_get_attachment_url($attachment_id)) . '%',
				'%' . $wpdb->esc_like('wp-image-' . $attachment_id) . '%'
			));
		
			// Check if used as featured image
			$used_as_thumbnail = $wpdb->get_var($wpdb->prepare(
				"SELECT COUNT(*) FROM $wpdb->postmeta 
				WHERE post_id != %d 
				AND meta_key = '_thumbnail_id' 
				AND meta_value = %d",
				$current_post_id,
				$attachment_id
			));
		
			return ($used_in_content > 0 || $used_as_thumbnail > 0);
		}

		/**
		 * Get authors
		 *
		 * This method retrieves a list of authors from the database and returns them in a JSON response.
		 *
		 * @return void
		 */
		public static function get_authors( $request_data ) {
			$search = isset($request_data['search']) ? sanitize_text_field($request_data['search']) : '';

			// Setup arguments
			$args = array(
				'orderby' => 'display_name',
			);
		
			// Add search parameter if provided
			if ( ! empty( $search ) ) {
				$args['search'] = '*' . $search . '*';
				$args['search_columns'] = array( 'display_name' );
			}

			// Create the WP_User_Query object
			$user_query = new WP_User_Query( $args );

			// Get the list of authors
			$authors = $user_query->get_results();

			// Initialize empty array
			$authordata = array();

			// Check if authors were found
			if ( ! empty( $authors ) ) {
				// Loop through each author
				foreach ( $authors as $author ) {
					// Add author data to array
					$authordata[] = array(
						'id'   => $author->ID,
						'name' => "{$author->data->display_name}",
					);
				}
			}

			if ( $authordata ) {
				wp_send_json_success( [
					'message' => 'Authors found: ' . count( $authordata ),
					'authors' => $authordata
				] );
			} else {
				wp_send_json_error( [
					'message' => 'No authors found'
				] );
			}

			wp_die();
		}

		/**
		 * Get all categories and filter based on search word
		 *
		 * @param $request_data
		 * @return void
		 */
		public static function get_categories( $request_data ) {
			$search = isset($request_data['search']) ? sanitize_text_field($request_data['search']) : '';
			$hide_empty = isset($request_data['hide_empty']) && $request_data['hide_empty'] === 'true';
	
			$args = array(
				'hide_empty' => $hide_empty,
			);
	
			if (!empty($search)) {
				$args['search'] = $search;
			}
	
			$categories = get_categories($args);
			$categories_array = array();
	
			foreach ($categories as $category) {
				$categories_array[] = array(
					'id' => $category->term_id,
					'name' => $category->name,
					'slug' => $category->slug,
					'description' => $category->description,
					'count' => $category->count,
				);
			}
	
			if (empty($categories_array)) {
				wp_send_json_error(['message' => 'No categories found']);
			} else {
				wp_send_json_success([
					'message'    => 'Categories retrieved successfully',
					'categories' => $categories_array,
				]);
			}
	
			wp_die();
		}
	
		/**
		 * Get all tags and filter based on search word
		 *
		 * @param $request_data
		 * @return void
		 */
		public static function get_tags( $request_data ) {
			$search = isset($request_data['search']) ? sanitize_text_field($request_data['search']) : '';
			$hide_empty = isset($request_data['hide_empty']) && $request_data['hide_empty'] === 'true';

			$args = array(
				'hide_empty' => $hide_empty,
			);

			if (!empty($search)) {
				$args['search'] = $search;
			}

			$tags = get_tags($args);
			$tags_array = array();

			foreach ($tags as $tag) {
				$tags_array[] = array(
					'id' => $tag->term_id,
					'name' => $tag->name,
					'slug' => $tag->slug,
					'description' => $tag->description,
					'count' => $tag->count,
				);
			}

			if (empty($tags_array)) {
				wp_send_json_error(['message' => 'No tags found']);
			} else {
				wp_send_json_success([
					'message'    => 'Tags retrieved successfully',
					'tags' => $tags_array,
				]);
			}

			wp_die();
		}

		/**
		 * Get all taxonomies and their terms
		 *
		 * @return void
		 */
		public static function get_taxonomies_terms() {
			// Get all taxonomies
			$taxonomies    = get_taxonomies( '', 'objects' );
			$taxonomy_data = array();

			// Check if taxonomies were found
			if ( ! empty( $taxonomies ) ) {
				// Loop through each taxonomy
				foreach ( $taxonomies as $taxonomy ) {
					// Get terms for the taxonomy
					$terms = get_terms( array(
						'taxonomy'   => $taxonomy->name,
						'hide_empty' => false
					) );
					// Initialize empty array for this taxonomy
					$term_data = array();

					if ( ! empty( $terms ) ) {
						// Loop through each term
						foreach ( $terms as $term ) {
							// Add term data to array
							$term_data[] = array(
								'ID'   => $term->term_id,
								'name' => $term->name,
								'slug' => $term->slug,
							);
						}
					}

					// Add term data to taxonomy_data under the taxonomy name
					$taxonomy_data[ $taxonomy->label ] = $term_data;
				}
			}

			if ( $taxonomy_data ) {
				wp_send_json_success( [
					'message'    => 'Taxonomies and terms found',
					'taxonomies' => $taxonomy_data
				] );
			} else {
				wp_send_json_error( [
					'message' => 'No taxonomies or terms found'
				] );
			}

			wp_die();
		}

		/**
		 * Upload image from URL to WordPress media library
		 * 
		 * @param string $image_url The URL of the image to upload
		 * @param array $meta_data Optional metadata like alt text and caption
		 * @return array|WP_Error Response array or WP_Error on failure
		 */
		public static function upload_image_from_url($image_url, $meta_data = array()) {			
			require_once(ABSPATH . 'wp-admin/includes/media.php');
			require_once(ABSPATH . 'wp-admin/includes/file.php');
			require_once(ABSPATH . 'wp-admin/includes/image.php');

			// Download image from URL
			$temp_file = download_url($image_url);
			if (is_wp_error($temp_file)) {
				return $temp_file;
			}

			// Get file name and force PNG type
			$file_name = basename($image_url) . '.png';
			$file_type = array('type' => 'image/png');

			// Prepare file array
			$file = array(
				'name'     => $file_name,
				'type'     => $file_type['type'],
				'tmp_name' => $temp_file,
				'error'    => 0,
				'size'     => filesize($temp_file)
			);

			// Move file to uploads directory
			$upload = wp_handle_sideload(
				$file,
				array('test_form' => false)
			);

			// Clean up temporary file
			@unlink($temp_file);

			if (isset($upload['error'])) {
				return new WP_Error('upload_error', $upload['error']);
			}

			// Prepare attachment data
			$attachment = array(
				'post_mime_type' => 'image/png',
				'post_title'     => sanitize_file_name($file_name),
				'post_content'   => '',
				'post_status'    => 'inherit'
			);

			// Insert attachment into database
			$attach_id = wp_insert_attachment($attachment, $upload['file']);

			if (is_wp_error($attach_id)) {
				@unlink($upload['file']);
				return $attach_id;
			}

			// Generate metadata
			$attach_data = wp_generate_attachment_metadata($attach_id, $upload['file']);
			wp_update_attachment_metadata($attach_id, $attach_data);

			// Set alt text if provided
			if (!empty($meta_data['alt_text'])) {
				update_post_meta($attach_id, '_wp_attachment_image_alt', 
					sanitize_text_field($meta_data['alt_text'])
				);
			}

			// Set caption if provided
			if (!empty($meta_data['caption'])) {
				wp_update_post(array(
					'ID' => $attach_id,
					'post_excerpt' => sanitize_text_field($meta_data['caption'])
				));
			}

			return array(
				'id' => $attach_id,
				'url' => wp_get_attachment_url($attach_id),
				'alt' => get_post_meta($attach_id, '_wp_attachment_image_alt', true),
				'caption' => get_post_field('post_excerpt', $attach_id)
			);
		}

		/**
		 * Parse markdown image string to get URL, alt text, and caption
		 * Format: ![alt text](url "caption")
		 *
		 * @param string $markdown_string The markdown image string
		 * @return array Array containing url, alt_text, and caption
		 */
		private static function parse_markdown_image($markdown_string) {
			$result = array(
				'url' => '',
				'alt_text' => '',
				'caption' => ''
			);

			// Match the markdown image pattern
			if (preg_match('/!\[(.*?)\]\((.*?)( ".*?")?\)/', $markdown_string, $matches)) {
				$result['alt_text'] = $matches[1];
				$result['url'] = $matches[2];
				
				// Extract caption if exists
				if (isset($matches[3])) {
					$result['caption'] = trim($matches[3], ' "');
				}
			}

			return $result;
		}

		/**
		 * Sets up ACF fields for a given post.
		 *
		 * @param array $acf_fields The array of key-value pairs from the user
		 * @param integer $post_id The ID of the post to set fields for.
		 *
		 * @return void
		 */
		private static function setup_acf_fields($acf_fields, $post_id) {
			if (!function_exists('acf_get_field_groups') || !function_exists('acf_get_fields')) {
				return;
			}

			// Get all ACF field groups
			$field_groups = acf_get_field_groups(array('post_id' => $post_id));
			
			// Create a map of all available fields
			$available_fields = array();
			foreach ($field_groups as $field_group) {
				$fields = acf_get_fields($field_group['key']);
				if (!$fields) {
					continue;
				}
				
				foreach ($fields as $field) {
					$available_fields[$field['name']] = $field;
				}
			}

			// Process each field from the user input
			foreach ($acf_fields as $field_key => $field_value) {
				// Skip if field doesn't exist in ACF
				if (!isset($available_fields[$field_key])) {
					continue;
				}

				$field_config = $available_fields[$field_key];
				
				// Handle field based on its type
				switch ($field_config['type']) {
					case 'gallery':
						if (is_array($field_value)) {
							$gallery_ids = array();
							foreach ($field_value as $image_markdown) {
								if (is_string($image_markdown)) {
									$image_data = self::parse_markdown_image($image_markdown);
									if (!empty($image_data['url'])) {
										$attachment_id = self::upload_image_from_url($image_data['url'], array(
											'alt_text' => $image_data['alt_text'],
											'caption' => $image_data['caption']
										));
										if (!is_wp_error($attachment_id)) {
											$gallery_ids[] = $attachment_id['id'];
										}
									}
								}
							}
							if (!empty($gallery_ids)) {
								update_field($field_key, $gallery_ids, $post_id);
							}
						}
						break;

					case 'image':
						if (is_string($field_value)) {
							$image_data = self::parse_markdown_image($field_value);
							if (!empty($image_data['url'])) {
								$attachment_id = self::upload_image_from_url($image_data['url'], array(
									'alt_text' => $image_data['alt_text'],
									'caption' => $image_data['caption']
								));
								if (!is_wp_error($attachment_id)) {
									update_field($field_key, $attachment_id['id'], $post_id);
								}
							}
						}
						break;

					case 'file':
						if (is_string($field_value)) {
							$attachment_id = self::upload_file_from_url($field_value);
							if (!is_wp_error($attachment_id)) {
								update_field($field_key, $attachment_id, $post_id);
							}
						}
						break;

					case 'repeater':
						if (is_array($field_value)) {
							$processed_rows = array();
							foreach ($field_value as $row) {
								if (is_array($row)) {
									$processed_row = array();
									foreach ($field_config['sub_fields'] as $sub_field) {
										if (isset($row[$sub_field['name']])) {
											$processed_row[$sub_field['name']] = $row[$sub_field['name']];
										}
									}
									if (!empty($processed_row)) {
										$processed_rows[] = $processed_row;
									}
								}
							}
							if (!empty($processed_rows)) {
								update_field($field_key, $processed_rows, $post_id);
							}
						}
						break;

					case 'flexible_content':
						if (is_array($field_value)) {
							$processed_layouts = array();
							foreach ($field_value as $layout) {
								if (isset($layout['acf_fc_layout']) && is_array($layout)) {
									$layout_name = $layout['acf_fc_layout'];
									if (isset($field_config['layouts'][$layout_name])) {
										$processed_layouts[] = $layout;
									}
								}
							}
							if (!empty($processed_layouts)) {
								update_field($field_key, $processed_layouts, $post_id);
							}
						}
						break;

					case 'relationship':
					case 'post_object':
						if (is_array($field_value)) {
							$post_ids = array_map('intval', $field_value);
							update_field($field_key, $post_ids, $post_id);
						} elseif (is_numeric($field_value)) {
							update_field($field_key, intval($field_value), $post_id);
						}
						break;

					case 'taxonomy':
						if (is_array($field_value)) {
							$term_ids = array_map('intval', $field_value);
							update_field($field_key, $term_ids, $post_id);
						} elseif (is_numeric($field_value)) {
							update_field($field_key, intval($field_value), $post_id);
						}
						break;

					default:
						update_field($field_key, $field_value, $post_id);
						break;
				}
			}
		}

		/**
		 * Upload a file from URL and return the attachment ID
		 *
		 * @param string $url The URL of the file to upload
		 * @return int|WP_Error The attachment ID or WP_Error on failure
		 */
		private static function upload_file_from_url($url) {
			require_once(ABSPATH . 'wp-admin/includes/file.php');
			require_once(ABSPATH . 'wp-admin/includes/media.php');
			require_once(ABSPATH . 'wp-admin/includes/image.php');

			$tmp = download_url($url);
			if (is_wp_error($tmp)) {
				return $tmp;
			}

			$file_array = array(
				'name' => basename($url),
				'tmp_name' => $tmp
			);

			$id = media_handle_sideload($file_array, 0);
			if (is_wp_error($id)) {
				@unlink($tmp);
				return $id;
			}

			return $id;
		}
	}
}
