<?php
/**
 * Export Theme Class
 *
 * @author Jegstudio
 * @since 1.0.0
 * @package gutenverse-themes-builder
 */

namespace Gutenverse_Themes_Builder;

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

use Gutenverse_Themes_Builder\Database\Database;
use Gutenverse_Themes_Builder\Export\Misc;
use ZipArchive;
use RecursiveIteratorIterator;
use RecursiveDirectoryIterator;

/**
 * Export Theme Class
 *
 * @package gutenverse-themes-builder
 */
class Export_Backup {

	/**
	 * Zipped file result
	 *
	 * @var $fileresult
	 */
	public $fileresult;

	/**
	 * List of Images
	 *
	 * @var array
	 */
	private $image_list = array();

	/**
	 * List of Menus
	 *
	 * @var array
	 */
	private $menu_list = array();

	/**
	 * List of Post Tag
	 *
	 * @var array
	 */
	private $post_tag_list = array();

	/**
	 * List of Post Category
	 *
	 * @var array
	 */
	private $post_category_list = array();

	/**
	 * Init constructor.
	 */
	public function __construct() {
		$this->start();
	}

	/**
	 * Export Theme
	 */
	public function start() {
		$theme_id   = get_option( 'gtb_active_theme_id' );
		$info_db    = Database::instance()->theme_info;
		$theme_data = $info_db->get_theme_data( $theme_id );
		$data       = $theme_data[0];
		$global_id  = $data['global_id'];
		$theme_slug = $data['slug'];

		require_once ABSPATH . 'wp-admin/includes/file.php';
		WP_Filesystem();
		global $wp_filesystem;

		/**Start */
		$path = $this->create_backup_folder( $theme_id, $theme_slug );

		if ( ! empty( $path ) ) {
			$this->export_themes_data_to_json( $wp_filesystem, $path, $data );
			$this->export_assets_to_json( $wp_filesystem, $path, $theme_id );
			$this->export_globals_to_json( $wp_filesystem, $path, $global_id );
			$this->export_patterns_to_json( $wp_filesystem, $path, $theme_id );
			$this->export_pages_to_json( $wp_filesystem, $path, $theme_id );
			$this->export_templates_to_json( $wp_filesystem, $path, $theme_id );
			$this->export_posts_to_json( $wp_filesystem, $path );
			$this->export_images( $wp_filesystem, $path );
			$this->export_image_list_to_json( $wp_filesystem, $path );
			$this->export_nav_menus_to_json( $wp_filesystem, $path );
			$this->extractor_send_file( $path, $theme_slug . '_gtb_' . $theme_id );
		}

		$this->remove_temp_folder( $path );
	}

	/**
	 * Export Posts
	 *
	 * @param object $wp_filesystem .
	 * @param string $path .
	 * @return void
	 */
	private function export_posts_to_json( $wp_filesystem, $path ) {
		$args = array(
			'post_type'      => 'post',
			'posts_per_page' => -1, // get all posts
			'post_status'    => 'publish',
		);

		$posts       = get_posts( $args );
		$post_folder = $path . '/posts';
		wp_mkdir_p( $post_folder );

		foreach ( $posts as $post ) {
			$post_id = $post->ID;
			$content = $post->post_content;

			$content = $this->extract_images( $content, 'page', $post_id );
			$content = $this->extract_menus( $content );

			$featured_image           = get_the_post_thumbnail_url( $post_id, 'full' );
			$image_without_resolution = gutenverse_themes_builder_get_image_without_resolution( $featured_image );
			if ( $image_without_resolution ) {
				$placeholder = $image_without_resolution['nores'];
			} else {
				$placeholder = $featured_image;
			}

			$valid_image_arr = explode( '/', $placeholder );
			$valid_name      = $valid_image_arr[ count( $valid_image_arr ) - 1 ];
			$this->add_image( $placeholder, 'post_featured_image', $valid_name );

			$post_data = array(
				'ID'             => $post->ID,
				'title'          => $post->post_title,
				'name'           => $post->post_name,
				'content'        => $content,
				'excerpt'        => get_the_excerpt( $post_id ),
				'featured_image' => array(
					'name' => $valid_name,
					'url'  => $placeholder,
				),
			);

			/** Categories */
			$categories = get_the_terms( $post_id, 'category' );

			if ( ! empty( $categories ) && ! is_wp_error( $categories ) ) {
				$post_categories = array();
				foreach ( $categories as $category ) {
					$collected_data = array();

					$this->get_all_post_taxonomies( $category, 'category', $this->post_category_list );

					$collected_data['slug'] = $category->slug;
					$collected_data['name'] = html_entity_decode( $category->name, ENT_QUOTES, 'UTF-8' );
					$this->add_taxonomy( $collected_data, $this->post_category_list );
					$post_categories[] = $collected_data;
				}
			}
			$post_data['categories'] = $post_categories;

			/** Tags */
			$tags = get_the_terms( $post_id, 'post_tag' );

			if ( ! empty( $tags ) && ! is_wp_error( $tags ) ) {
				$post_tags = array();
				foreach ( $tags as $tag ) {
					$collected_data = array();

					$this->get_all_post_taxonomies( $tag, 'post_tag', $this->post_tag_list );

					$collected_data['slug'] = $tag->slug;
					$collected_data['name'] = html_entity_decode( $tag->name, ENT_QUOTES, 'UTF-8' );
					$post_tags[]            = $collected_data;
				}
			}
			$post_data['tags'] = $post_tags;

			$json_data = wp_json_encode( $post_data, JSON_PRETTY_PRINT );

			if ( false === $json_data ) {
				error_log( 'Failed to encode post data to JSON.' );
				continue;
			}

			$file_name = sanitize_file_name( $post->post_name . '.json' );
			$file_path = $post_folder . '/' . $file_name;

			if ( $wp_filesystem->put_contents( $file_path, $json_data, FS_CHMOD_FILE ) ) {
				continue;
			} else {
				error_log( 'Failed to write JSON file to ' . $file_path );
				continue;
			}
		}
		$categories_json_data = wp_json_encode( $this->post_category_list, JSON_PRETTY_PRINT );

		if ( $categories_json_data ) {
			$category_path = $path . '/post_categories.json';
			$add_file      = $wp_filesystem->put_contents( $category_path, $categories_json_data, FS_CHMOD_FILE );
			if ( ! $add_file ) {
				error_log( 'Failed to write JSON file to ' . $category_path );
			}
		} else {
			error_log( 'Failed to encode post data to JSON.' );
		}

		$tags_json_data = wp_json_encode( $this->post_tag_list, JSON_PRETTY_PRINT );

		if ( $tags_json_data ) {
			$tag_path = $path . '/post_tags.json';
			$add_file = $wp_filesystem->put_contents( $tag_path, $tags_json_data, FS_CHMOD_FILE );
			if ( ! $add_file ) {
				error_log( 'Failed to write JSON file to ' . $tag_path );

			}
		} else {
			error_log( 'Failed to encode post data to JSON.' );
		}
	}

	/**
	 * Get Taxonomies Parent
	 *
	 * @param object $taxonomy .
	 * @param string $type .
	 * @param array  $global_collection .
	 */
	private function get_all_post_taxonomies( $taxonomy, $type, &$global_collection ) {
		$arr_taxonomy = array(
			'slug'   => $taxonomy->slug,
			'name'   => html_entity_decode( $taxonomy->name, ENT_QUOTES, 'UTF-8' ),
			'parent' => '',
		);
		if ( 0 !== $taxonomy->parent ) {
			$parent_id = $taxonomy->parent;
			$parent    = get_term( $parent_id, $type );

			if ( $parent && ! is_wp_error( $parent ) ) {
				$arr_taxonomy['parent'] = $parent->slug;
				$this->get_all_post_taxonomies( $parent, $type, $global_collection );
			}
		}

		$this->add_taxonomy( $arr_taxonomy, $global_collection );
	}

	/**
	 * Add Taxonomy
	 *
	 * @param array $taxonomy .
	 * @param array $collections .
	 */
	private function add_taxonomy( $taxonomy, &$collections ) {
		if ( $taxonomy['slug'] ) {
			$ids = array_column( $collections, 'slug' );
			if ( array_search( $taxonomy['slug'], $ids, true ) === false ) {
				$collections[] = $taxonomy;
			}
		}
	}

	/**
	 * Recursively removes a directory and all its contents using WP_Filesystem.
	 *
	 * @param string $dir The directory path to remove.
	 * @return bool True on success, false on failure.
	 */
	private function remove_temp_folder( $dir ) {
		global $wp_filesystem;

		if ( empty( $wp_filesystem ) ) {
			if ( ! function_exists( 'WP_Filesystem' ) ) {
				require_once ABSPATH . 'wp-admin/includes/file.php';
			}
			$init = WP_Filesystem();
			if ( ! $init ) {
				return false;
			}
		}

		if ( ! $wp_filesystem->is_dir( $dir ) ) {
			return false;
		}

		$files = $wp_filesystem->dirlist( $dir );

		if ( is_array( $files ) ) {
			foreach ( $files as $file => $properties ) {
				if ( 'd' === $properties['type'] && ! $this->remove_temp_folder( trailingslashit( $dir ) . $file ) ) {
					// Recursively remove subdirectory.
					return false;
				} elseif ( ! $wp_filesystem->delete( trailingslashit( $dir ) . $file ) ) {
					return false;
				}
			}
		}

		return $wp_filesystem->rmdir( $dir );
	}

	/**
	 * Create backup folders
	 *
	 * @param string $theme_id .
	 * @param string $theme_slug .
	 */
	private function create_backup_folder( $theme_id, $theme_slug ) {
		if ( ! current_user_can( 'manage_options' ) ) {
			return false;
		}

		$upload_dir  = wp_upload_dir();
		$target_path = $upload_dir['basedir'] . '/gtb_backup/' . $theme_slug . '_gtb_' . $theme_id;

		$this->remove_temp_folder( $target_path );

		if ( wp_mkdir_p( $target_path ) ) {
			return $target_path;
		} else {
			error_log( 'Failed to create backup folder: ' . $target_path );
			return false;
		}
	}

	/**
	 * Export themes data to json
	 *
	 * @param mixed  $wp_filesystem .
	 * @param string $path .
	 * @param array  $data .
	 */
	private function export_themes_data_to_json( $wp_filesystem, $path, $data = array() ) {
		$theme_data = maybe_unserialize( $data['theme_data'] );
		$other      = maybe_unserialize( $data['other'] );

		$data_export = $data;

		$data_export['theme_data'] = $theme_data;
		$data_export['other']      = $other;

		$this->export_themes_screenshots( $other );

		$json_data = json_encode( $data_export, JSON_PRETTY_PRINT );
		if ( false === $json_data ) {
			error_log( 'Failed to encode post data to JSON.' );
			return false;
		}

		$file_name = sanitize_file_name( 'theme_details.json' );
		$file_path = $path . '/' . $file_name;

		if ( $wp_filesystem->put_contents( $file_path, $json_data, FS_CHMOD_FILE ) ) {
			return true;
		} else {
			error_log( 'Failed to write JSON file to ' . $file_path );
			return false;
		}
	}

	/**
	 * Export theme screenshots
	 *
	 * @param array $data .
	 */
	private function export_themes_screenshots( $data = array() ) {
		if ( empty( $data['screenshots'] ) ) {
			return;
		}

		if ( ! empty( $data['screenshots']['thumbnail'] ) ) {
			$thumbnail = $data['screenshots']['thumbnail'];
			$this->add_image( $thumbnail['url'], 'thumbnail', $thumbnail['filename'], $thumbnail['id'] );
		}

		if ( ! empty( $data['screenshots']['dashboard'] ) ) {
			$dashboard = $data['screenshots']['dashboard'];

			foreach ( $dashboard as $image ) {
				$this->add_image( $image['url'], 'dashboard', $image['filename'], $image['id'] );
			}
		}
	}

	/**
	 * Export css/js assets to json
	 *
	 * @param mixed  $wp_filesystem .
	 * @param string $path .
	 * @param string $theme_id .
	 */
	private function export_assets_to_json( $wp_filesystem, $path, $theme_id ) {
		$assets_db = Database::instance()->theme_assets;
		$assets    = $assets_db->get_all_assets( $theme_id );

		$json_data = json_encode( $assets, JSON_PRETTY_PRINT );
		if ( false === $json_data ) {
			error_log( 'Failed to encode post data to JSON.' );
			return false;
		}

		$file_name = sanitize_file_name( 'assets.json' );
		$file_path = $path . '/' . $file_name;

		if ( $wp_filesystem->put_contents( $file_path, $json_data, FS_CHMOD_FILE ) ) {
			return true;
		} else {
			error_log( 'Failed to write JSON file to ' . $file_path );
			return false;
		}
	}

	/**
	 * Export global variables to json
	 *
	 * @param mixed  $wp_filesystem .
	 * @param string $path .
	 * @param string $global_id .
	 */
	private function export_globals_to_json( $wp_filesystem, $path, $global_id ) {
		$global_db = Database::instance()->theme_globals;
		$global    = $global_db->get_data( $global_id );

		$json_data = json_encode( $global, JSON_PRETTY_PRINT );
		if ( false === $json_data ) {
			error_log( 'Failed to encode post data to JSON.' );
			return false;
		}

		$file_name = sanitize_file_name( 'globals.json' );
		$file_path = $path . '/' . $file_name;

		if ( $wp_filesystem->put_contents( $file_path, $json_data, FS_CHMOD_FILE ) ) {
			return true;
		} else {
			error_log( 'Failed to write JSON file to ' . $file_path );
			return false;
		}
	}

	/**
	 * Export patterns to json
	 *
	 * @param mixed  $wp_filesystem .
	 * @param string $path .
	 * @param string $theme_id .
	 */
	private function export_patterns_to_json( $wp_filesystem, $path, $theme_id ) {
		$patterns = new \WP_Query(
			array(
				'post_type'      => 'gutenverse-pattern',
				'posts_per_page' => -1,
				'meta_query'     => array( //phpcs:ignore
					array(
						'key'     => '_pattern_theme_id',
						'value'   => $theme_id,
						'compare' => '===',
					),
				),
			)
		);

		$pattern_folder = $path . '/patterns';
		wp_mkdir_p( $pattern_folder );

		foreach ( $patterns->posts as &$post ) {
			$pattern_category = get_post_meta( $post->ID, '_pattern_category', true );
			$pattern_sync     = get_post_meta( $post->ID, '_pattern_sync', true );

			$post->post_content = $this->extract_images( $post->post_content, 'sync', $post->ID );
			$post->post_content = $this->extract_menus( $post->post_content );

			$meta = array(
				'category' => $pattern_category,
				'sync'     => $pattern_sync,
			);

			$json_post = array(
				'post_data' => $post,
				'post_meta' => $meta,
			);

			$json_data = json_encode( $json_post, JSON_PRETTY_PRINT );

			if ( false === $json_data ) {
				error_log( 'Failed to encode post data to JSON.' );
				continue;
			}

			$file_name = sanitize_file_name( $post->post_name . '.json' );
			$file_path = $pattern_folder . '/' . $file_name;

			if ( $wp_filesystem->put_contents( $file_path, $json_data, FS_CHMOD_FILE ) ) {
				continue;
			} else {
				error_log( 'Failed to write JSON file to ' . $file_path );
				continue;
			}
		}
	}

	/**
	 * Export pages to json
	 *
	 * @param mixed  $wp_filesystem .
	 * @param string $path .
	 * @param string $theme_id .
	 */
	private function export_pages_to_json( $wp_filesystem, $path, $theme_id ) {
		$pages = new \WP_Query(
			array(
				'post_type'      => 'page',
				'posts_per_page' => -1,
				'meta_query'     => array( //phpcs:ignore
					array(
						'key'     => '_gtb_page_theme_id',
						'value'   => $theme_id,
						'compare' => '===',
					),
				),
			)
		);

		$page_folder = $path . '/pages';
		wp_mkdir_p( $page_folder );

		foreach ( $pages->posts as &$post ) {
			$post->post_content = $this->extract_images( $post->post_content, 'page', $post->ID );
			$post->post_content = $this->extract_menus( $post->post_content );

			$template          = get_post_meta( $post->ID, '_wp_page_template', true );
			$page_preview      = get_post_meta( $post->ID, '_gtb_page_preview', true );
			$page_image_id     = get_post_meta( $post->ID, '_gtb_page_image', true );
			$is_homepage       = get_post_meta( $post->ID, '_gtb_page_is_homepage', true );
			$order             = get_post_meta( $post->ID, '_gtb_page_order', true );
			$page_image        = (object) array(
				'url'      => wp_get_attachment_url( $page_image_id ),
				'filename' => basename( wp_get_attachment_url( $page_image_id ) ),
				'id'       => $page_image_id,
			);
			$template_page_arr = explode( '-', $template );
			$template_page     = '';

			if ( 'gutenverse' === $template_page_arr[0] ) {
				$sliced_array  = array_slice( $template_page_arr, 1 );
				$template_page = implode( '-', $sliced_array );
			} else {
				$template_page = $template;
			}

			$meta = array(
				'template'         => $template_page,
				'page_preview'     => $page_preview ? $page_preview : '',
				'page_image'       => $page_image,
				'is_homepage'      => $is_homepage,
				'order'            => $order,
				'tb_used_template' => $template,
			);

			$json_post = array(
				'post_data' => $post,
				'post_meta' => $meta,
			);

			$json_data = json_encode( $json_post, JSON_PRETTY_PRINT );

			if ( false === $json_data ) {
				error_log( 'Failed to encode post data to JSON.' );
				continue;
			}

			$file_name = sanitize_file_name( $post->post_name . '.json' );
			$file_path = $page_folder . '/' . $file_name;

			if ( $wp_filesystem->put_contents( $file_path, $json_data, FS_CHMOD_FILE ) ) {
				continue;
			} else {
				error_log( 'Failed to write JSON file to ' . $file_path );
				continue;
			}
		}
	}

	/**
	 * Export templates to json
	 *
	 * @param mixed  $wp_filesystem .
	 * @param string $path .
	 * @param string $theme_id .
	 */
	private function export_templates_to_json( $wp_filesystem, $path, $theme_id ) {
		$templates_db    = Database::instance()->theme_templates;
		$templates_data  = $templates_db->get_data( $theme_id );
		$template_folder = $path . '/templates';
		wp_mkdir_p( $template_folder );

		$templates_content = get_block_templates(array(), 'wp_template'); // phpcs:ignore
		$parts_content     = get_block_templates(array(), 'wp_template_part'); // phpcs:ignore
		$html_content      = array();
		$categories        = array();

		foreach ( $templates_content as $template ) {
			$html_content[ $template->slug ] = $template->content;
		}

		foreach ( $parts_content as $part ) {
			$html_content[ $part->slug ] = $part->content;
		}

		foreach ( $templates_data as &$template_data ) {
			$category_folder = $template_folder . '/' . $template_data['category'];

			if ( ! is_dir( $category_folder ) ) {
				wp_mkdir_p( $category_folder );
			}

			if ( ! in_array( $template_data['category'], $categories, true ) ) {
				$categories[] = $template_data['category'];
			}

			$slug_key = strtolower( $template_data['category'] . '-' . Misc::sluggify( $template_data['name'] ) );

			$template_data['content'] = '';

			if ( ! empty( $html_content[ $slug_key ] ) ) {
				$template_data['content'] = $html_content[ $slug_key ];
			}

			$template_data['content'] = $this->extract_images( $template_data['content'], 'template' );
			$template_data['content'] = $this->extract_menus( $template_data['content'] );
			$template_data['content'] = $this->fix_template_part( $template_data['content'] );

			$json_data = json_encode( $template_data, JSON_PRETTY_PRINT );

			if ( false === $json_data ) {
				error_log( 'Failed to encode post data to JSON.' );
				continue;
			}

			$file_name = sanitize_file_name( Misc::sluggify( $template_data['name'] ) . '.json' );
			$file_path = $category_folder . '/' . $file_name;

			if ( $wp_filesystem->put_contents( $file_path, $json_data, FS_CHMOD_FILE ) ) {
				continue;
			} else {
				error_log( 'Failed to write JSON file to ' . $file_path );
				continue;
			}
		}

		$json_data = json_encode( $categories, JSON_PRETTY_PRINT );

		if ( false === $json_data ) {
			error_log( 'Failed to encode post data to JSON.' );
		}

		$file_name = sanitize_file_name( 'categories.json' );
		$file_path = $template_folder . '/' . $file_name;

		if ( $wp_filesystem->put_contents( $file_path, $json_data, FS_CHMOD_FILE ) ) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Fix template part
	 *
	 * @param mixed  $wp_filesystem .
	 * @param string $path .
	 */
	private function fix_template_part( $content ) {
		$pattern = '/<!--\s*wp:template-part\s+(\{.*?\})\s*\/-->/s';

		return preg_replace_callback(
			$pattern,
			function ( $matches ) {
				$jsonText = $matches[1];

				// Try to decode the JSON safely
				$data = json_decode( $jsonText, true );

				if ( is_array( $data ) && isset( $data['slug'] ) ) {
					$slug = $data['slug'];
				} else {
					// Fallback: regex to extract the slug string if json_decode fails
					if ( preg_match( '/"slug"\s*:\s*"([^"]*)"/', $jsonText, $m ) ) {
						$slug = $m[1];
					} else {
						// If no slug found, return original match unchanged
						return $matches[0];
					}
				}

				// Use json_encode to produce valid JSON for the replacement
				$slugObj = json_encode( array( 'slug' => $slug ), JSON_UNESCAPED_SLASHES );

				return '<!-- wp:template-part ' . $slugObj . ' /-->';
			},
			$content
		);
	}

	/**
	 * Export images
	 *
	 * @param mixed  $wp_filesystem .
	 * @param string $path .
	 */
	private function export_images( $wp_filesystem, $path ) {
		$target_path = trailingslashit( $path ) . 'images';

		wp_mkdir_p( $target_path );

		foreach ( $this->image_list as $key => $image_data ) {
			if ( ! empty( $image_data['image_url'] ) && ! empty( $image_data['name'] ) ) {
				$image_url  = $image_data['image_url'];
				$image_name = basename( $image_data['name'] );
				$clean_name = Misc::image_separate_resolution( $image_name );

				$file_path     = trailingslashit( $target_path ) . $clean_name;
				$image_content = @file_get_contents( $image_url );
				if ( false !== $image_content ) {
					$wp_filesystem->put_contents( $file_path, $image_content, FS_CHMOD_FILE );
				} else {
					// Remove from image_list if not found
					unset( $this->image_list[ $key ] );
					gutenverse_rlog( "Image not found, removed: {$image_url}" );
				}
			}
		}
	}

	/**
	 * Export global variables to json
	 *
	 * @param mixed  $wp_filesystem .
	 * @param string $path .
	 */
	private function export_image_list_to_json( $wp_filesystem, $path ) {
		$json_data = json_encode( $this->image_list, JSON_PRETTY_PRINT );
		if ( false === $json_data ) {
			error_log( 'Failed to encode post data to JSON.' );
			return false;
		}

		$file_name = sanitize_file_name( 'images.json' );
		$file_path = $path . '/' . $file_name;

		if ( $wp_filesystem->put_contents( $file_path, $json_data, FS_CHMOD_FILE ) ) {
			return true;
		} else {
			error_log( 'Failed to write JSON file to ' . $file_path );
			return false;
		}
	}

	/**
	 * Extract Images
	 *
	 * @param string  $content .
	 * @param string  $type .
	 * @param string  $parent_id .
	 * @param boolean $is_outside_pattern_wrapper .
	 */
	private function extract_images( $content, $type, $parent_id = '', $is_outside_pattern_wrapper = false ) {
		// Capture image url inside double quotes.
		preg_match_all( '/http[^"]*(?:\.png|\.jpg|\.svg|\.jpeg|\.gif|\.webp|\.json)/U', $content, $matches );
		if ( ! empty( $matches[0] ) ) {
			foreach ( $matches[0] as $image ) {
				/**Check if image have resolution in their name and extract image name*/
				$image_without_resolution = gutenverse_themes_builder_get_image_without_resolution( $image );
				if ( $image_without_resolution ) {
					$image_name  = $image_without_resolution['image_name'];
					$placeholder = $image_without_resolution['nores'];
				} else {
					$image_arr   = explode( '/', $image );
					$image_name  = $image_arr[ count( $image_arr ) - 1 ];
					$placeholder = $image;
				}

				$valid_image_arr = explode( '/', $placeholder );
				$valid_name      = $valid_image_arr[ count( $valid_image_arr ) - 1 ];

				/**Check the type of the image for image page and sync have different purpose than template and async */
				switch ( $type ) {
					case 'page':
					case 'sync':
						/**Filter image list to check if the same image and type already registered inside the array */
						$filter_data = array_filter(
							$this->image_list,
							function ( $obj ) use ( $image_name, $parent_id ) {
								return isset( $obj['name'] ) && $obj['name'] === $image_name && ( 'page' === $obj['type'] || 'sync' === $obj['type'] ) && $parent_id === $obj['id'];
							}
						);

						$images_id_with_the_same_name = new \WP_Query(
							array(
								'post_type'   => 'attachment',
								'post_status' => 'inherit',
								'meta_query'  => array(
									array(
										'key'     => '_wp_attached_file',
										'value'   => $valid_name,
										'compare' => 'LIKE',
									),
								),
							)
						);

						$image_id = 'null';
						if ( $images_id_with_the_same_name->have_posts() ) {
							foreach ( $images_id_with_the_same_name->posts as $image_post ) {
								$att_image      = wp_get_attachment_url( $image_post->ID );
								$att_image_arr  = explode( '/', $att_image );
								$att_image_name = $att_image_arr[ count( $att_image_arr ) - 1 ];
								if ( $att_image_name === $valid_name ) {
									$image_id = $image_post->ID;
								}
							}
						}

						/**Get the first value that have the condition or get null if no data found */
						$filter_image = reset( $filter_data );

						/**Add image to array image*/
						if ( ! $filter_image ) {
							$this->add_image( $placeholder, $type, $image_name, $parent_id, $image_id );
						}

						/**Replace image with uuid image */
						$content = str_replace( $image, $placeholder, $content );
						break;
					case 'template':
					case 'async':
					default:
						if ( $is_outside_pattern_wrapper ) {
							break;
						}

						/**Filter image list to check if the same image and type already registered inside the array */
						$filter_data  = array_filter(
							$this->image_list,
							function ( $obj ) use ( $image_name ) {
								return isset( $obj['name'] ) && $obj['name'] === $image_name && ( 'template' === $obj['type'] || 'async' === $obj['type'] );
							}
						);
						$filter_image = reset( $filter_data );

						/**Add image to image list then get uuid */
						if ( ! $filter_image ) {
							$this->add_image( $placeholder, $type, $image_name );
						}
						$content = str_replace( $image, $placeholder, $content );
						break;
				}
			}
		}
		return $content;
	}

	/**
	 * Extract Menu
	 *
	 * @param string $content .
	 */
	private function extract_menus( $content ) {
		preg_match_all( '/"menuId":(\d+)/', $content, $matches );
		if ( ! empty( $matches[0] ) ) {
			foreach ( $matches[1] as $match ) {
				$menu_id     = $match;
				$menu_object = wp_get_nav_menu_object( $menu_id );
				$menu_items  = wp_get_nav_menu_items( $menu_id );
				$arr_menu    = array();
				if ( $menu_items ) {
					foreach ( $menu_items as $item ) {
						$url         = $item->url;
						$object_slug = null;
						$parent_idx  = null;
						if ( 'page' === $item->object || 'post' === $item->object ) {
							$url         = '#';
							$post        = get_post( $item->object_id );
							$object_slug = str_replace( ' ', '-', strtolower( $post->post_title ) );
						}
						if ( 0 !== intval( $item->menu_item_parent ) ) {
							$parent_id = intval( $item->menu_item_parent );
							foreach ( $arr_menu as $key => $parent ) {
								if ( intval( $parent['id'] ) === $parent_id ) {
									$parent_idx = $key;
									break;
								}
							}
						}

						$arr_menu[] = array(
							'id'          => $item->ID,
							'title'       => $item->title,
							'url'         => $url,
							'parent'      => strval( $parent_idx ),
							'type'        => $item->object,
							'object_slug' => $object_slug,
							'have_child'  => false,
						);
						if ( null !== $parent_idx ) {
							$arr_menu[ $parent_idx ]['have_child'] = true;
						}
						$parent_idx = null;
					}
				}

				$placeholder = '"menuId":{{placeholderID' . $menu_id . '}}';
				$this->add_menus(
					array(
						'id'          => $menu_id,
						'slug'        => $menu_object->slug,
						'name'        => $menu_object->name,
						'data'        => $arr_menu,
						'placeholder' => '{{placeholderID' . $menu_id . '}}',
					)
				);

				$content = str_replace( '"menuId":' . $menu_id, $placeholder, $content );
			}
		}
		return $content;
	}

	/**
	 * Backup Menus
	 *
	 * @param mixed  $wp_filesystem .
	 * @param string $path .
	 */
	public function export_nav_menus_to_json( $wp_filesystem, $path ) {
		$json_data = json_encode( $this->menu_list, JSON_PRETTY_PRINT );
		if ( false === $json_data ) {
			error_log( 'Failed to encode post data to JSON.' );
			return false;
		}

		$file_name = sanitize_file_name( 'menus.json' );
		$file_path = $path . '/' . $file_name;

		if ( $wp_filesystem->put_contents( $file_path, $json_data, FS_CHMOD_FILE ) ) {
			return true;
		} else {
			error_log( 'Failed to write JSON file to ' . $file_path );
			return false;
		}
	}

	/**
	 * Add image to list
	 *
	 * @param string $image image url string .
	 * @param string $type type of image (template, page, sync, or async) string .
	 * @param string $name .
	 * @param string $id id of image master (page/pattern).
	 * @param string $image_id id of the image.
	 */
	private function add_image( $image, $type, $name, $id = '', $image_id = 'null' ) {
		$this->image_list[] = array(
			'name'      => $name,
			'image_url' => $image,
			'type'      => $type,
			'id'        => $id,
			'image_id'  => $image_id,
		);
	}

	/**
	 * Add Menu
	 *
	 * @param array $menus .
	 */
	private function add_menus( $menus ) {
		if ( $menus['slug'] ) {
			$ids = array_column( $this->menu_list, 'id' );
			if ( array_search( $menus['id'], $ids, true ) === false ) {
				$this->menu_list[] = $menus;
			}
		}
	}


	/**
	 * Send File to User.
	 *
	 * @param string $filepath .
	 * @param string $filename .
	 */
	private function extractor_send_file( $filepath, $filename ) {
		$zip_path = $filepath . '_backup.zip';

		$zip = new ZipArchive();
		$zip->open( $zip_path, ZipArchive::CREATE | ZipArchive::OVERWRITE );

		// Create recursive directory iterator.
		$files = new RecursiveIteratorIterator(
			new RecursiveDirectoryIterator( $filepath ),
			RecursiveIteratorIterator::LEAVES_ONLY
		);

		foreach ( $files as $file ) {
			if ( ! $file->isDir() ) {
				$file_path     = $file->getRealPath();
				$relative_path = substr( $file_path, strlen( trailingslashit( wp_upload_dir()['basedir'] . '/gtb_backup/' . $filename ) ) );
				$zip->addFile( $file_path, $relative_path );
			}
		}

		$zip->close();

		$this->fileresult = array(
			'filename' => $filename . '_backup.zip',
			'filepath' => $zip_path,
			'fileurl'  => wp_upload_dir()['baseurl'] . '/gtb_backup/' . $filename . '_backup.zip',
		);
	}

}
