<?php
/**
 * Post Handler
 *
 * @package Post_Export_Import_With_Media
 * @since 1.1.0
 */

// Prevent direct access
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Post Handler Class - Manages post export/import operations
 */
class PEIWM_Post_Handler {

	/**
	 * Instance
	 *
	 * @var PEIWM_Post_Handler|null
	 */
	private static $instance = null;

	/**
	 * Import results for detailed feedback
	 *
	 * @var array
	 */
	private $import_results = array();

	/**
	 * Get instance
	 *
	 * @return PEIWM_Post_Handler
	 */
	public static function get_instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Constructor
	 */
	private function __construct() {
		$this->init_ajax_hooks();
		$this->import_results = array();
	}

	/**
	 * Initialize AJAX hooks
	 */
	private function init_ajax_hooks() {
		add_action( 'wp_ajax_peiwm_export_posts', array( $this, 'ajax_export_posts' ) );
		add_action( 'wp_ajax_peiwm_export_posts_chunk', array( $this, 'ajax_export_posts_chunk' ) );
		add_action( 'wp_ajax_peiwm_import_post', array( $this, 'ajax_import_post' ) );
		add_action( 'wp_ajax_peiwm_delete_posts', array( $this, 'ajax_delete_posts' ) );
		add_action( 'wp_ajax_peiwm_check_and_download_image', array( $this, 'ajax_check_and_download_image' ) );
		add_action( 'wp_ajax_peiwm_get_posts_list', array( $this, 'ajax_get_posts_list' ) );
	}

	/**
	 * AJAX: Export posts
	 */
	public function ajax_export_posts() {
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'peiwm_secure_nonce' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Security check failed', 'post-export-import-with-media' ) ) );
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Permission denied', 'post-export-import-with-media' ) ) );
		}

		try {
			@ini_set( 'memory_limit', '512M' );

			// Support selective export by post IDs
			$selected_ids = isset( $_POST['post_ids'] ) ? array_map( 'absint', explode( ',', sanitize_text_field( wp_unslash( $_POST['post_ids'] ) ) ) ) : array();

			$query_args = array(
				'post_type'              => 'post',
				'numberposts'            => -1,
				'post_status'            => array( 'publish', 'draft', 'private', 'pending' ),
				'orderby'                => 'date',
				'order'                  => 'DESC',
				'no_found_rows'          => true,
				'update_post_term_cache' => false,
			);

			if ( ! empty( $selected_ids ) ) {
				$query_args['post__in'] = $selected_ids;
				$query_args['orderby']  = 'post__in';
			}

			$posts = get_posts( $query_args );

			$export_data = array();
			global $wpdb;
			foreach ( $posts as $post ) {
				$post_data = array(
					'ID'            => absint( $post->ID ),
					'post_title'    => sanitize_text_field( $post->post_title ),
					'post_content'  => wp_kses_post( $post->post_content ),
					'post_excerpt'  => sanitize_textarea_field( $post->post_excerpt ),
					'post_status'   => sanitize_key( $post->post_status ),
					'post_type'     => sanitize_key( $post->post_type ),
					'post_author'   => absint( $post->post_author ),
					'post_date'     => sanitize_text_field( $post->post_date ),
					'post_modified' => sanitize_text_field( $post->post_modified ),
					'post_name'     => sanitize_title( $post->post_name ),
					'post_format'   => get_post_format( $post->ID ) ?: 'standard',
					'categories'    => $this->get_post_categories_secure( $post->ID ),
					'tags'          => $this->get_post_tags_secure( $post->ID ),
					'meta'          => $this->get_post_meta_secure( $post->ID ),
					'featured_image' => $this->get_featured_image_secure( $post->ID ),
					'content_images' => $this->get_content_images_secure( $post->post_content ),
					'acf_fields'    => array(),
				);

				// Enrich with author identity data for smart mapping on import
				$author_id   = absint( $post->post_author );
				$author_user = get_userdata( $author_id );

				if ( $author_user ) {
					// phpcs:disable WordPress.DB.DirectDatabaseQuery
					$author_pass_hash = $wpdb->get_var( $wpdb->prepare(
						"SELECT user_pass FROM {$wpdb->users} WHERE ID = %d",
						$author_user->ID
					) );
					// phpcs:enable WordPress.DB.DirectDatabaseQuery

					$post_data['post_author_data'] = array(
						'user_login'    => sanitize_user( $author_user->user_login ),
						'user_email'    => sanitize_email( $author_user->user_email ),
						'display_name'  => sanitize_text_field( $author_user->display_name ),
						'role'          => ! empty( $author_user->roles )
						                   ? sanitize_text_field( $author_user->roles[0] )
						                   : 'subscriber',
						'user_pass_hash' => $author_pass_hash ? $author_pass_hash : null,
					);
				} else {
					$post_data['post_author_data'] = null;
				}

				// ACF fields export — only if checkbox was sent AND ACF is active
				$export_acf_fields = isset( $_POST['export_acf_fields'] ) && '1' === sanitize_key( $_POST['export_acf_fields'] );
				if ( $export_acf_fields && class_exists( 'PEIM_CPT_ACF_Exporter' ) ) {
					$acf_exporter = PEIM_CPT_ACF_Exporter::get_instance();
					if ( $acf_exporter->is_acf_active() ) {
						$acf_raw = get_fields( $post->ID );
						if ( ! empty( $acf_raw ) && is_array( $acf_raw ) ) {
							$post_data['acf_fields'] = $acf_exporter->flatten_acf_fields_public( $post->ID, $acf_raw );
						}
					}
				}

				$export_data[] = $post_data;			}

			wp_reset_postdata();

			wp_send_json_success( array(
				'data'  => $export_data,
				'count' => count( $export_data ),
			) );

		} catch ( Exception $e ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Export failed. Please try again.', 'post-export-import-with-media' ) ) );
		}
	}

	/**
	 * AJAX: Export posts in a single chunk (offset + limit) for large sites
	 */
	public function ajax_export_posts_chunk() {
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'peiwm_secure_nonce' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Security check failed', 'post-export-import-with-media' ) ) );
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Permission denied', 'post-export-import-with-media' ) ) );
		}

		try {
			@ini_set( 'memory_limit', '512M' );

			$offset     = isset( $_POST['offset'] ) ? absint( $_POST['offset'] ) : 0;
			$chunk_size = isset( $_POST['chunk_size'] ) ? absint( $_POST['chunk_size'] ) : 50;
			$chunk_size = max( 1, min( $chunk_size, 100 ) );

			// Support session key for large ID lists (avoids max_input_vars truncation)
			$session_key  = isset( $_POST['export_session'] ) ? sanitize_text_field( wp_unslash( $_POST['export_session'] ) ) : '';
			$selected_ids = array();
			$new_session_key = $session_key;

			if ( ! empty( $session_key ) ) {
				// Retrieve IDs from existing transient
				$stored = get_transient( 'peiwm_export_ids_' . $session_key );
				if ( is_array( $stored ) ) {
					$selected_ids    = $stored;
					$new_session_key = $session_key; // reuse same key
				}
			} elseif ( isset( $_POST['post_ids'] ) && ! empty( $_POST['post_ids'] ) ) {
				$selected_ids = array_map( 'absint', explode( ',', sanitize_text_field( wp_unslash( $_POST['post_ids'] ) ) ) );
				// Store in transient for subsequent chunks so we don't re-send all IDs
				$new_session_key = wp_generate_uuid4();
				set_transient( 'peiwm_export_ids_' . $new_session_key, $selected_ids, HOUR_IN_SECONDS );
			}

			$query_args = array(
				'post_type'              => 'post',
				'numberposts'            => $chunk_size,
				'offset'                 => $offset,
				'post_status'            => array( 'publish', 'draft', 'private', 'pending', 'future' ),
				'orderby'                => 'date',
				'order'                  => 'DESC',
				'no_found_rows'          => true,
				'update_post_term_cache' => false,
			);

			if ( ! empty( $selected_ids ) ) {
				$chunk_ids = array_slice( $selected_ids, $offset, $chunk_size );
				if ( empty( $chunk_ids ) ) {
					wp_send_json_success( array(
						'data'         => array(),
						'count'        => 0,
						'has_more'     => false,
						'offset'       => $offset,
						'session_key'  => $new_session_key,
					) );
				}
				$query_args['post__in']    = $chunk_ids;
				$query_args['orderby']     = 'post__in';
				$query_args['numberposts'] = count( $chunk_ids );
				unset( $query_args['offset'] );
			}

			$posts       = get_posts( $query_args );
			$export_data = array();
			global $wpdb;

			foreach ( $posts as $post ) {
				$post_data = array(
					'ID'            => absint( $post->ID ),
					'post_title'    => sanitize_text_field( $post->post_title ),
					'post_content'  => wp_kses_post( $post->post_content ),
					'post_excerpt'  => sanitize_textarea_field( $post->post_excerpt ),
					'post_status'   => sanitize_key( $post->post_status ),
					'post_type'     => sanitize_key( $post->post_type ),
					'post_author'   => absint( $post->post_author ),
					'post_date'     => sanitize_text_field( $post->post_date ),
					'post_modified' => sanitize_text_field( $post->post_modified ),
					'post_name'     => sanitize_title( $post->post_name ),
					'post_format'   => get_post_format( $post->ID ) ?: 'standard',
					'categories'     => $this->get_post_categories_secure( $post->ID ),
					'tags'           => $this->get_post_tags_secure( $post->ID ),
					'meta'           => $this->get_post_meta_secure( $post->ID ),
					'featured_image' => $this->get_featured_image_secure( $post->ID ),
					'content_images' => $this->get_content_images_secure( $post->post_content ),
					'acf_fields'    => array(),
				);

				// Enrich with author identity data for smart mapping on import
				$author_id   = absint( $post->post_author );
				$author_user = get_userdata( $author_id );

				if ( $author_user ) {
					// phpcs:disable WordPress.DB.DirectDatabaseQuery
					$author_pass_hash = $wpdb->get_var( $wpdb->prepare(
						"SELECT user_pass FROM {$wpdb->users} WHERE ID = %d",
						$author_user->ID
					) );
					// phpcs:enable WordPress.DB.DirectDatabaseQuery

					$post_data['post_author_data'] = array(
						'user_login'    => sanitize_user( $author_user->user_login ),
						'user_email'    => sanitize_email( $author_user->user_email ),
						'display_name'  => sanitize_text_field( $author_user->display_name ),
						'role'          => ! empty( $author_user->roles )
						                   ? sanitize_text_field( $author_user->roles[0] )
						                   : 'subscriber',
						'user_pass_hash' => $author_pass_hash ? $author_pass_hash : null,
					);
				} else {
					$post_data['post_author_data'] = null;
				}

				// ACF fields export — only if checkbox was sent AND ACF is active
				$chunk_export_acf = isset( $_POST['export_acf_fields'] ) && '1' === sanitize_key( $_POST['export_acf_fields'] );
				if ( $chunk_export_acf && class_exists( 'PEIM_CPT_ACF_Exporter' ) ) {
					$acf_exporter_chunk = PEIM_CPT_ACF_Exporter::get_instance();
					if ( $acf_exporter_chunk->is_acf_active() ) {
						$acf_raw_chunk = get_fields( $post->ID );
						if ( ! empty( $acf_raw_chunk ) && is_array( $acf_raw_chunk ) ) {
							$post_data['acf_fields'] = $acf_exporter_chunk->flatten_acf_fields_public( $post->ID, $acf_raw_chunk );
						}
					}
				}

				$export_data[] = $post_data;
			}

			wp_reset_postdata();

			$has_more = count( $posts ) === $chunk_size;
			if ( ! empty( $selected_ids ) ) {
				$has_more = ( $offset + count( $posts ) ) < count( $selected_ids );
			}

			wp_send_json_success( array(
				'data'        => $export_data,
				'count'       => count( $export_data ),
				'has_more'    => $has_more,
				'offset'      => $offset,
				'session_key' => $new_session_key,
			) );

		} catch ( Exception $e ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Export chunk failed.', 'post-export-import-with-media' ), 'debug' => $e->getMessage() ) );
		}
	}

	/**
	 * AJAX: Get posts list (paginated - 500 per page to avoid memory exhaustion)
	 */
	public function ajax_get_posts_list() {
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'peiwm_secure_nonce' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Security check failed', 'post-export-import-with-media' ) ) );
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Permission denied', 'post-export-import-with-media' ) ) );
		}

		try {
			@ini_set( 'memory_limit', '512M' );

			// Use configured page size: batch mode uses export_list_page_size, regular mode uses 300
			$batch_settings  = PEIWM_Batch_Settings::get_instance();
			$batch_enabled   = $batch_settings->is_batch_enabled();
			$page_size       = $batch_enabled
				? (int) $batch_settings->get_setting( 'export_list_page_size' )
				: 300;
			$page_size       = max( 10, min( $page_size, 2000 ) );
			$offset          = isset( $_POST['offset'] ) ? absint( $_POST['offset'] ) : 0;

			// Get total count using same statuses as the query
			$counts      = wp_count_posts( 'post' );
			$total_count = (int) ( $counts->publish ?? 0 )
				+ (int) ( $counts->draft ?? 0 )
				+ (int) ( $counts->private ?? 0 )
				+ (int) ( $counts->pending ?? 0 )
				+ (int) ( $counts->future ?? 0 );

			$large_site      = $total_count >= 800;
			$show_batch_warn = $large_site && ! $batch_enabled;
			$large_site      = $total_count >= 800;
			$show_batch_warn = $large_site && ! $batch_enabled;

			$posts = get_posts( array(
				'post_type'              => 'post',
				'numberposts'            => $page_size,
				'offset'                 => $offset,
				'post_status'            => array( 'publish', 'draft', 'private', 'pending', 'future' ),
				'orderby'                => 'date',
				'order'                  => 'DESC',
				'no_found_rows'          => true,
				'update_post_meta_cache' => false,
				'update_post_term_cache' => false,
			) );

			$list = array();
			foreach ( $posts as $post ) {
				$list[] = array(
					'ID'          => absint( $post->ID ),
					'post_title'  => sanitize_text_field( $post->post_title ),
					'post_date'   => sanitize_text_field( $post->post_date ),
					'post_status' => sanitize_key( $post->post_status ),
				);
			}

			wp_reset_postdata();

			wp_send_json_success( array(
				'posts'           => $list,
				'count'           => count( $list ),
				'total_count'     => $total_count,
				'offset'          => $offset,
				'page_size'       => $page_size,
				'has_more'        => ( $offset + count( $list ) ) < $total_count,
				'show_batch_warn' => $show_batch_warn,
				'batch_enabled'   => $batch_enabled,
			) );

		} catch ( Exception $e ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Failed to load posts list.', 'post-export-import-with-media' ), 'debug' => $e->getMessage() ) );
		}
	}

	/**
	 * AJAX: Import post
	 */
	public function ajax_import_post() {
		// CRITICAL: Close session early to allow concurrent requests
		if ( session_id() ) {
			session_write_close();
		}
		
		// Set reasonable execution time limit
		@set_time_limit( 90 );
		@ini_set( 'max_execution_time', '90' );
		
		// Optimize memory - each concurrent request needs its own budget
		@ini_set( 'memory_limit', '256M' );
		
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'peiwm_secure_nonce' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Security check failed', 'post-export-import-with-media' ) ) );
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Permission denied', 'post-export-import-with-media' ) ) );
		}

		try {
			$post_data_raw = isset( $_POST['post_data'] ) ? wp_unslash( $_POST['post_data'] ) : ''; //phpcs:ignore we have sanitize below with sanitize_post_data
			$download_missing_images = isset( $_POST['download_missing_images'] ) && $_POST['download_missing_images'] === '1';
			$check_media_library = isset( $_POST['check_media_library'] ) && $_POST['check_media_library'] === '1';

			// Smart author mapping options (new in v1.5.0, backward compatible)
			$smart_author_mapping = ! isset( $_POST['peiwm_smart_author_mapping'] ) || '1' === sanitize_key( $_POST['peiwm_smart_author_mapping'] );
			$fallback_behavior    = isset( $_POST['peiwm_author_fallback'] )
			                        ? sanitize_text_field( wp_unslash( $_POST['peiwm_author_fallback'] ) )
			                        : 'current_user';
			if ( ! in_array( $fallback_behavior, array( 'current_user', 'create_user' ), true ) ) {
				$fallback_behavior = 'current_user';
			}
			
			if ( empty( $post_data_raw ) ) {
				throw new Exception( esc_html__( 'No post data provided', 'post-export-import-with-media' ) );
			}
			
			$post_data = json_decode( $post_data_raw, true );
			
			if ( json_last_error() !== JSON_ERROR_NONE ) {
				throw new Exception( esc_html__( 'Invalid JSON data provided', 'post-export-import-with-media' ) );
			}

			if ( ! $post_data || ! is_array( $post_data ) ) {
				throw new Exception( esc_html__( 'Invalid post data', 'post-export-import-with-media' ) );
			}

			$sanitized_post_data = $this->sanitize_post_data( $post_data ); // Sanitize input data properly

			// Apply force_status override if provided
			$force_status = isset( $_POST['force_status'] ) ? sanitize_key( wp_unslash( $_POST['force_status'] ) ) : 'original';
			$allowed_statuses = array( 'publish', 'draft', 'private', 'pending' );
			if ( $force_status !== 'original' && in_array( $force_status, $allowed_statuses, true ) ) {
				$sanitized_post_data['post_status'] = $force_status;
			}

			// Resolve author ID using smart mapping (backward compatible)
			$author_data_raw = isset( $post_data['post_author_data'] ) && is_array( $post_data['post_author_data'] )
			                   ? $post_data['post_author_data']
			                   : null;
			$original_author_id = isset( $post_data['post_author'] ) ? absint( $post_data['post_author'] ) : 0;

			if ( $smart_author_mapping ) {
				$resolved_author_id = $this->resolve_post_author( $original_author_id, $author_data_raw, $fallback_behavior );
			} else {
				$resolved_author_id = ( $original_author_id > 0 && false !== get_userdata( $original_author_id ) )
				                      ? $original_author_id
				                      : get_current_user_id();
			}

			// Check if post already exists
			$existing_posts = get_posts( array(
				'post_type'      => 'post',
				'post_status'    => 'any',
				'title'          => $sanitized_post_data['post_title'],
				'posts_per_page' => 1,
			) );

			if ( ! empty( $existing_posts ) ) {
				$existing_post = $existing_posts[0];
				// If force_status is set and differs from current, update the status
				if ( $force_status !== 'original' && in_array( $force_status, $allowed_statuses, true ) && $existing_post->post_status !== $force_status ) {
					wp_update_post( array(
						'ID'          => $existing_post->ID,
						'post_status' => $force_status,
					) );
					wp_reset_postdata();
					wp_send_json_success( array(
						'status' => 'updated',
						'reason' => sprintf( 'Status updated to %s', $force_status ),
					) );
				}
				wp_send_json_success( array(
					'status' => 'skipped',
					'reason' => esc_html__( 'Post already exists', 'post-export-import-with-media' ),
				) );
			}

			// Insert post
			$post_id = wp_insert_post( array(
				'post_title'    => $sanitized_post_data['post_title'],
				'post_content'  => $sanitized_post_data['post_content'],
				'post_excerpt'  => $sanitized_post_data['post_excerpt'],
				'post_status'   => $sanitized_post_data['post_status'],
				'post_type'     => $sanitized_post_data['post_type'],
				'post_author'   => $resolved_author_id,
				'post_date'     => $sanitized_post_data['post_date'],
				'post_name'     => $sanitized_post_data['post_name'], // slug
			) );

			if ( is_wp_error( $post_id ) ) {
				throw new Exception( sprintf(
					esc_html__( 'Failed to create post: %s', 'post-export-import-with-media' ),
					$post_id->get_error_message()
				) );
			}

			// Set post format
			if ( ! empty( $sanitized_post_data['post_format'] ) && $sanitized_post_data['post_format'] !== 'standard' ) {
				set_post_format( $post_id, $sanitized_post_data['post_format'] );
			}

			// Import categories
			if ( ! empty( $sanitized_post_data['categories'] ) ) {
				$this->import_post_categories_secure( $post_id, $sanitized_post_data['categories'] );
			}

			// Import tags
			if ( ! empty( $sanitized_post_data['tags'] ) ) {
				$this->import_post_tags_secure( $post_id, $sanitized_post_data['tags'] );
			}

			// Import meta data
			if ( ! empty( $sanitized_post_data['meta'] ) && is_array( $sanitized_post_data['meta'] ) ) {
				$this->import_post_meta_secure( $post_id, $sanitized_post_data['meta'] );
			}

			// Import ACF fields if present and ACF/class is available
			if ( ! empty( $sanitized_post_data['acf_fields'] ) && is_array( $sanitized_post_data['acf_fields'] ) && class_exists( 'PEIM_CPT_ACF_Exporter' ) ) {
				$acf_importer = PEIM_CPT_ACF_Exporter::get_instance();
				if ( $acf_importer->is_acf_active() || true ) { // fall back to raw meta if ACF inactive
					$acf_importer->import_acf_fields_public( $post_id, $sanitized_post_data['acf_fields'] );
				}
			}

			// Import content images first and update post content
			$updated_content = $sanitized_post_data['post_content'];
			if ( $check_media_library && ! empty( $sanitized_post_data['content_images'] ) ) {
				$updated_content = $this->import_content_images_secure( $post_id, $sanitized_post_data['content_images'], $sanitized_post_data['post_content'], $download_missing_images );
			}
			// If not checking media, we skip image processing entirely - images remain as placeholders in content

			// Import featured image
			if ( $check_media_library && ! empty( $sanitized_post_data['featured_image'] ) ) {
				$this->import_featured_image_secure( $post_id, $sanitized_post_data['featured_image'], $download_missing_images );
			}

			// Update post content if it was modified
			if ( $updated_content !== $sanitized_post_data['post_content'] ) {
				wp_update_post( array(
					'ID' => $post_id,
					'post_content' => $updated_content,
				) );
			}

			// Reset global post data once at the end
			wp_reset_postdata();
			
			// Clear object cache to prevent memory buildup
			wp_cache_flush();

			// Get detailed import results
			$import_results = $this->get_import_results();
			
			// Check if any images were missing
			$missing_images = $this->check_missing_images( $sanitized_post_data );
			$message = 'Post imported successfully';
			if ( ! empty( $missing_images ) ) {
				if ( $download_missing_images ) {
					$message .= '. Note: ' . count( $missing_images ) . ' image(s) not found and could not be downloaded.';
				} else {
					$message .= '. Note: ' . count( $missing_images ) . ' image(s) not found in media library. Import media files first or enable "Download missing images".';
				}
			}

			wp_send_json_success( array(
				'status'  => 'imported',
				'post_id' => $post_id,
				'message' => $message,
				'missing_images' => $missing_images,
				'download_enabled' => $download_missing_images,
				'import_details' => $import_results,
			) );

		} catch ( Exception $e ) {
			// Clear cache on error too
			wp_cache_flush();
			wp_send_json_error( array( 'message' => esc_html__( 'Import failed. Please check the file format.', 'post-export-import-with-media' ) ) );
		}
	}

	/**
	 * AJAX: Check and download individual image
	 */
	public function ajax_check_and_download_image() {
		// CRITICAL: Close session early to allow concurrent requests
		if ( session_id() ) {
			session_write_close();
		}
		
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'peiwm_secure_nonce' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Security check failed', 'post-export-import-with-media' ) ) );
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Permission denied', 'post-export-import-with-media' ) ) );
		}

		try {
			$image_data_raw = isset( $_POST['image_data'] ) ? wp_unslash( $_POST['image_data'] ) : ''; //phpcs:ignore we have sanitize below with sanitize_file_name
			$post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;
			
			if ( empty( $image_data_raw ) ) {
				throw new Exception( esc_html__( 'No image data provided', 'post-export-import-with-media' ) );
			}
			
			$image_data = json_decode( $image_data_raw, true );
			
			if ( json_last_error() !== JSON_ERROR_NONE ) {
				throw new Exception( esc_html__( 'Invalid JSON data provided', 'post-export-import-with-media' ) );
			}

			if ( ! $image_data || ! is_array( $image_data ) ) {
				throw new Exception( esc_html__( 'Invalid image data', 'post-export-import-with-media' ) );
			}

			$filename = isset( $image_data['filename'] ) ? sanitize_file_name( $image_data['filename'] ) : ''; // Sanitize input data properly
			if ( empty( $filename ) ) {
				throw new Exception( esc_html__( 'No filename provided', 'post-export-import-with-media' ) );
			}

			// Try to find existing attachment by filename
			$attachment_id = $this->find_existing_attachment_by_filename( $filename );

			if ( $attachment_id ) {
				wp_send_json_success( array(
					'status' => 'found_local',
					'attachment_id' => $attachment_id,
					'message' => 'Found in media library',
				) );
			}

			// Try to download from URL
			$image_url = isset( $image_data['url'] ) ? esc_url_raw( $image_data['url'] ) : '';
			if ( empty( $image_url ) ) {
				wp_send_json_success( array(
					'status' => 'failed',
					'message' => 'No URL provided for download',
				) );
			}

			$image_title = isset( $image_data['title'] ) ? sanitize_text_field( $image_data['title'] ) : '';
			$image_alt = isset( $image_data['alt'] ) ? sanitize_text_field( $image_data['alt'] ) : '';

			$attachment_id = $this->download_and_create_attachment( $image_url, $post_id, $image_title, $image_alt );

			if ( $attachment_id && ! is_wp_error( $attachment_id ) ) {
				wp_send_json_success( array(
					'status' => 'downloaded',
					'attachment_id' => $attachment_id,
					'message' => 'Successfully downloaded',
				) );
			} else {
				wp_send_json_success( array(
					'status' => 'failed',
					'message' => 'Download failed',
				) );
			}

		} catch ( Exception $e ) {
			wp_send_json_error( array( 'message' => $e->getMessage() ) );
		}
	}

	/**
	 * AJAX: Delete posts
	 */
	public function ajax_delete_posts() {
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'peiwm_secure_nonce' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Security check failed', 'post-export-import-with-media' ) ) );
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Permission denied', 'post-export-import-with-media' ) ) );
		}

		try {
			$posts = get_posts( array(
				'post_type'   => 'post',
				'numberposts' => -1,
				'post_status' => 'any',
			) );

			if ( empty( $posts ) ) {
				wp_reset_postdata(); // Reset before returning
				wp_send_json_success( array( 'message' => esc_html__( 'No posts found to delete', 'post-export-import-with-media' ) ) );
			}

			$deleted_count = 0;
			$failed_count = 0;

			foreach ( $posts as $post ) {
				$result = wp_delete_post( $post->ID, true );
				if ( $result ) {
					$deleted_count++;
				} else {
					$failed_count++;
				}
			}

			// Reset global post data after operations
			wp_reset_postdata();

			$message = sprintf(
				esc_html__( 'Deleted %d posts successfully', 'post-export-import-with-media' ),
				$deleted_count
			);

			if ( $failed_count > 0 ) {
				$message .= sprintf(
					esc_html__( '. Failed to delete %d posts.', 'post-export-import-with-media' ),
					$failed_count
				);
			}

			wp_send_json_success( array(
				'message'       => $message,
				'deleted_count' => $deleted_count,
				'failed_count'  => $failed_count,
				'total_count'   => count( $posts ),
			) );

		} catch ( Exception $e ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Delete operation failed. Please try again.', 'post-export-import-with-media' ) ) );
		}
	}

	/**
	 * Get post meta securely
	 *
	 * @param int $post_id Post ID
	 * @return array Post meta
	 */
	private function get_post_meta_secure( $post_id ) {
		$meta = get_post_meta( $post_id );
		$secure_meta = array();

		foreach ( $meta as $key => $values ) {
			if ( ! str_starts_with( $key, '_' ) ) { // Skip private meta
				$secure_meta[ sanitize_key( $key ) ] = array_map( 'sanitize_text_field', $values );
			}
		}

		return $secure_meta;
	}

	/**
	 * Get featured image securely
	 *
	 * @param int $post_id Post ID
	 * @return array|null Featured image data
	 */
	private function get_featured_image_secure( $post_id ) {
		$thumbnail_id = get_post_thumbnail_id( $post_id );
		
		if ( ! $thumbnail_id ) {
			return null;
		}

		$attachment = get_post( $thumbnail_id );
		if ( ! $attachment ) {
			return null;
		}

		return array(
			'id'       => absint( $thumbnail_id ),
			'url'      => esc_url( wp_get_attachment_url( $thumbnail_id ) ),
			'title'    => sanitize_text_field( $attachment->post_title ),
			'alt'      => sanitize_text_field( get_post_meta( $thumbnail_id, '_wp_attachment_image_alt', true ) ),
			'filename' => sanitize_file_name( basename( get_attached_file( $thumbnail_id ) ) ),
		);
	}

	/**
	 * Sanitize post data
	 *
	 * @param array $post_data Raw post data
	 * @return array Sanitized post data
	 */
	private function sanitize_post_data( $post_data ) {
		return array(
			'post_title'    => isset( $post_data['post_title'] ) ? sanitize_text_field( $post_data['post_title'] ) : '',
			'post_content'  => isset( $post_data['post_content'] ) ? $this->sanitize_gutenberg_content( $post_data['post_content'] ) : '',
			'post_excerpt'  => isset( $post_data['post_excerpt'] ) ? sanitize_textarea_field( $post_data['post_excerpt'] ) : '',
			'post_status'   => isset( $post_data['post_status'] ) ? sanitize_key( $post_data['post_status'] ) : 'draft',
			'post_type'     => isset( $post_data['post_type'] ) ? sanitize_key( $post_data['post_type'] ) : 'post',
			'post_author'   => isset( $post_data['post_author'] ) ? absint( $post_data['post_author'] ) : get_current_user_id(),
			'post_date'     => isset( $post_data['post_date'] ) ? sanitize_text_field( $post_data['post_date'] ) : current_time( 'mysql' ),
			'post_name'     => isset( $post_data['post_name'] ) ? sanitize_title( $post_data['post_name'] ) : '',
			'post_format'   => isset( $post_data['post_format'] ) ? sanitize_key( $post_data['post_format'] ) : 'standard',
			'categories'    => isset( $post_data['categories'] ) && is_array( $post_data['categories'] ) ? $post_data['categories'] : array(),
			'tags'          => isset( $post_data['tags'] ) && is_array( $post_data['tags'] ) ? $post_data['tags'] : array(),
			'meta'          => isset( $post_data['meta'] ) && is_array( $post_data['meta'] ) ? $post_data['meta'] : array(),
			'featured_image' => isset( $post_data['featured_image'] ) ? $post_data['featured_image'] : null,
			'content_images' => isset( $post_data['content_images'] ) && is_array( $post_data['content_images'] ) ? $post_data['content_images'] : array(),
			'acf_fields'    => isset( $post_data['acf_fields'] ) && is_array( $post_data['acf_fields'] ) ? $post_data['acf_fields'] : array(),
		);
	}
	 
	 /**
	 * @param int   $post_id Post ID
	 * @param array $meta_data Meta data
	 */
	private function import_post_meta_secure( $post_id, $meta_data ) {
		foreach ( $meta_data as $key => $values ) {
			$safe_key = sanitize_key( $key );
			
			if ( empty( $safe_key ) || str_starts_with( $safe_key, '_' ) ) {
				continue; // Skip invalid or private keys
			}

			delete_post_meta( $post_id, $safe_key );
			
			foreach ( (array) $values as $value ) {
				add_post_meta( $post_id, $safe_key, sanitize_text_field( $value ) );
			}
		}
	}

	/**
	 * Import featured image securely
	 *
	 * @param int   $post_id Post ID
	 * @param array $image_data Image data
	 * @param bool  $download_missing Whether to download missing images
	 */
	private function import_featured_image_secure( $post_id, $image_data, $download_missing = false ) {
		if ( ! is_array( $image_data ) || empty( $image_data['filename'] ) ) {
			return;
		}

		$filename = sanitize_file_name( $image_data['filename'] );
		$image_alt = isset( $image_data['alt'] ) ? sanitize_text_field( $image_data['alt'] ) : '';

		// Try to find existing attachment by filename
		$attachment_id = $this->find_existing_attachment_by_filename( $filename );

		if ( $attachment_id ) {
			// Record that featured image was found locally
			$this->import_results[] = array(
				'type' => 'found_local',
				'filename' => $filename,
				'attachment_id' => $attachment_id,
				'message' => 'Found featured image in media library: ' . $filename,
			);
			set_post_thumbnail( $post_id, $attachment_id );
			
			if ( ! empty( $image_alt ) ) {
				update_post_meta( $attachment_id, '_wp_attachment_image_alt', $image_alt );
			}

			// Fix _wp_attached_file meta to ensure proper srcset generation
			$this->fix_attachment_meta( $attachment_id );
		} else if ( $download_missing && ! empty( $image_data['url'] ) ) {
			// Try to download the featured image from original URL
			$image_url = esc_url_raw( $image_data['url'] );
			$image_title = isset( $image_data['title'] ) ? sanitize_text_field( $image_data['title'] ) : '';
			
			$attachment_id = $this->download_and_create_attachment( $image_url, $post_id, $image_title, $image_alt );
			
			if ( $attachment_id && ! is_wp_error( $attachment_id ) ) {
				set_post_thumbnail( $post_id, $attachment_id );
			}
			// If download failed, featured image will be reported as missing
		}
	}

	/**
	 * Get content images securely
	 *
	 * @param string $content Post content
	 * @return array Content images data
	 */
	private function get_content_images_secure( $content ) {
		$images = array();
		
		// Extract image IDs from wp:image blocks
		preg_match_all( '/wp:image\s+{[^}]*"id":(\d+)[^}]*}/', $content, $matches );
		if ( ! empty( $matches[1] ) ) {
			foreach ( $matches[1] as $image_id ) {
				$attachment_id = absint( $image_id );
				if ( $attachment_id > 0 ) {
					$image_data = $this->get_attachment_data_secure( $attachment_id );
					if ( $image_data ) {
						$images[] = $image_data;
					}
				}
			}
		}

		// Also extract from img tags with wp-image class
		preg_match_all( '/class="[^"]*wp-image-(\d+)[^"]*"/', $content, $matches );
		if ( ! empty( $matches[1] ) ) {
			foreach ( $matches[1] as $image_id ) {
				$attachment_id = absint( $image_id );
				if ( $attachment_id > 0 ) {
					$image_data = $this->get_attachment_data_secure( $attachment_id );
					if ( $image_data ) {
						// Check if we already have this image
						$exists = false;
						foreach ( $images as $existing_image ) {
							if ( $existing_image['id'] === $attachment_id ) {
								$exists = true;
								break;
							}
						}
						if ( ! $exists ) {
							$images[] = $image_data;
						}
					}
				}
			}
		}

		return $images;
	}

	/**
	 * Get attachment data securely
	 *
	 * @param int $attachment_id Attachment ID
	 * @return array|null Attachment data
	 */
	private function get_attachment_data_secure( $attachment_id ) {
		$attachment = get_post( $attachment_id );
		if ( ! $attachment || $attachment->post_type !== 'attachment' ) {
			return null;
		}

		return array(
			'id'       => absint( $attachment_id ),
			'url'      => esc_url( wp_get_attachment_url( $attachment_id ) ),
			'title'    => sanitize_text_field( $attachment->post_title ),
			'alt'      => sanitize_text_field( get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) ),
			'filename' => sanitize_file_name( basename( get_attached_file( $attachment_id ) ) ),
		);
	}

	/**
	 * Get post categories securely
	 *
	 * @param int $post_id Post ID
	 * @return array Categories data
	 */
	private function get_post_categories_secure( $post_id ) {
		$categories = get_the_category( $post_id );
		$category_data = array();

		foreach ( $categories as $category ) {
			$category_data[] = array(
				'term_id' => absint( $category->term_id ),
				'name' => sanitize_text_field( $category->name ),
				'slug' => sanitize_title( $category->slug ),
				'description' => sanitize_textarea_field( $category->description ),
			);
		}

		return $category_data;
	}

	/**
	 * Get post tags securely
	 *
	 * @param int $post_id Post ID
	 * @return array Tags data
	 */
	private function get_post_tags_secure( $post_id ) {
		$tags = get_the_tags( $post_id );
		$tag_data = array();

		if ( $tags ) {
			foreach ( $tags as $tag ) {
				$tag_data[] = array(
					'term_id' => absint( $tag->term_id ),
					'name' => sanitize_text_field( $tag->name ),
					'slug' => sanitize_title( $tag->slug ),
					'description' => sanitize_textarea_field( $tag->description ),
				);
			}
		}

		return $tag_data;
	}

	/**
	 * Import post categories securely
	 *
	 * @param int   $post_id Post ID
	 * @param array $categories_data Categories data
	 */
	private function import_post_categories_secure( $post_id, $categories_data ) {
		$category_ids = array();

		foreach ( $categories_data as $category_data ) {
			if ( ! is_array( $category_data ) || empty( $category_data['name'] ) ) {
				continue;
			}

			$category_name = sanitize_text_field( $category_data['name'] );
			$category_slug = isset( $category_data['slug'] ) ? sanitize_title( $category_data['slug'] ) : '';
			$category_description = isset( $category_data['description'] ) ? sanitize_textarea_field( $category_data['description'] ) : '';

			// Check if category exists
			$existing_category = get_category_by_slug( $category_slug );
			if ( ! $existing_category ) {
				$existing_category = get_term_by( 'name', $category_name, 'category' );
			}

			if ( $existing_category ) {
				$category_ids[] = $existing_category->term_id;
			} else {
				// Create new category
				$new_category = wp_insert_term( $category_name, 'category', array(
					'slug' => $category_slug,
					'description' => $category_description,
				) );

				if ( ! is_wp_error( $new_category ) ) {
					$category_ids[] = $new_category['term_id'];
				}
			}
		}

		if ( ! empty( $category_ids ) ) {
			wp_set_post_categories( $post_id, $category_ids );
		}
	}

	/**
	 * Import post tags securely
	 *
	 * @param int   $post_id Post ID
	 * @param array $tags_data Tags data
	 */
	private function import_post_tags_secure( $post_id, $tags_data ) {
		$tag_names = array();

		foreach ( $tags_data as $tag_data ) {
			if ( ! is_array( $tag_data ) || empty( $tag_data['name'] ) ) {
				continue;
			}

			$tag_name = sanitize_text_field( $tag_data['name'] );
			$tag_slug = isset( $tag_data['slug'] ) ? sanitize_title( $tag_data['slug'] ) : '';
			$tag_description = isset( $tag_data['description'] ) ? sanitize_textarea_field( $tag_data['description'] ) : '';

			// Check if tag exists
			$existing_tag = get_term_by( 'slug', $tag_slug, 'post_tag' );
			if ( ! $existing_tag ) {
				$existing_tag = get_term_by( 'name', $tag_name, 'post_tag' );
			}

			if ( $existing_tag ) {
				$tag_names[] = $tag_name;
			} else {
				// Create new tag
				$new_tag = wp_insert_term( $tag_name, 'post_tag', array(
					'slug' => $tag_slug,
					'description' => $tag_description,
				) );

				if ( ! is_wp_error( $new_tag ) ) {
					$tag_names[] = $tag_name;
				}
			}
		}

		if ( ! empty( $tag_names ) ) {
			wp_set_post_tags( $post_id, $tag_names );
		}
	}

	/**
	 * Find existing attachment by filename
	 *
	 * @param string $filename Filename to search for
	 * @return int|null Attachment ID if found
	 */
	private function find_existing_attachment_by_filename( $filename ) {
		global $wpdb;
		
		// Use direct database query for better performance
		$attachment_id = $wpdb->get_var( $wpdb->prepare(
			"SELECT post_id FROM {$wpdb->postmeta} 
			WHERE meta_key = '_wp_attached_file' 
			AND meta_value LIKE %s 
			LIMIT 1",
			'%' . $wpdb->esc_like( $filename )
		) );

		if ( $attachment_id ) {
			return absint( $attachment_id );
		}

		// If not found, try searching by post title (filename without extension)
		$title = pathinfo( $filename, PATHINFO_FILENAME );
		$attachment_id = $wpdb->get_var( $wpdb->prepare(
			"SELECT ID FROM {$wpdb->posts} 
			WHERE post_type = 'attachment' 
			AND post_title = %s 
			LIMIT 1",
			$title
		) );

		return $attachment_id ? absint( $attachment_id ) : null;
	}

	/**
	 * Import content images securely and update content URLs
	 *
	 * @param int    $post_id Post ID
	 * @param array  $images_data Images data
	 * @param string $content Original content
	 * @param bool   $download_missing Whether to download missing images
	 * @return string Updated content
	 */
	private function import_content_images_secure( $post_id, $images_data, $content, $download_missing = false ) {
		$updated_content = $content;
		$url_mapping = array();

		foreach ( $images_data as $image_data ) {
			if ( ! is_array( $image_data ) || empty( $image_data['filename'] ) ) {
				continue;
			}

			$filename = sanitize_file_name( $image_data['filename'] );
			$image_title = isset( $image_data['title'] ) ? sanitize_text_field( $image_data['title'] ) : '';
			$image_alt = isset( $image_data['alt'] ) ? sanitize_text_field( $image_data['alt'] ) : '';
			$old_url = isset( $image_data['url'] ) ? esc_url_raw( $image_data['url'] ) : '';

			// Try to find existing attachment by filename
			$attachment_id = $this->find_existing_attachment_by_filename( $filename );

			if ( $attachment_id ) {
				// Record that image was found locally
				$this->import_results[] = array(
					'type' => 'found_local',
					'filename' => $filename,
					'attachment_id' => $attachment_id,
					'message' => 'Found in media library: ' . $filename,
				);
				// Set alt text if provided
				if ( ! empty( $image_alt ) ) {
					update_post_meta( $attachment_id, '_wp_attachment_image_alt', $image_alt );
				}

				// Fix _wp_attached_file meta to ensure proper srcset generation
				$this->fix_attachment_meta( $attachment_id );

				// Get new URL
				$new_url = wp_get_attachment_url( $attachment_id );
				if ( $new_url && ! empty( $old_url ) ) {
					$url_mapping[ $old_url ] = $new_url;
				}
				
				// Update image ID references in content
				if ( isset( $image_data['id'] ) ) {
					$old_id = absint( $image_data['id'] );
					// Update wp:image blocks
					$updated_content = preg_replace(
						'/("id":)' . $old_id . '([,}])/',
						'${1}' . $attachment_id . '${2}',
						$updated_content
					);
					// Update wp-image class
					$updated_content = str_replace(
						'wp-image-' . $old_id,
						'wp-image-' . $attachment_id,
						$updated_content
					);
				}
			} else if ( $download_missing && ! empty( $old_url ) ) {
				// Try to download the image from original URL
				$attachment_id = $this->download_and_create_attachment( $old_url, $post_id, $image_title, $image_alt );
				
				if ( $attachment_id && ! is_wp_error( $attachment_id ) ) {
					// Successfully downloaded and created attachment
					$new_url = wp_get_attachment_url( $attachment_id );
					if ( $new_url ) {
						$url_mapping[ $old_url ] = $new_url;
					}
					
					// Update image ID references in content
					if ( isset( $image_data['id'] ) ) {
						$old_id = absint( $image_data['id'] );
						// Update wp:image blocks
						$updated_content = preg_replace(
							'/("id":)' . $old_id . '([,}])/',
							'${1}' . $attachment_id . '${2}',
							$updated_content
						);
						// Update wp-image class
						$updated_content = str_replace(
							'wp-image-' . $old_id,
							'wp-image-' . $attachment_id,
							$updated_content
						);
					}
				}
				// If download failed, image will be reported as missing
			}
		}

		// Replace old URLs with new ones
		foreach ( $url_mapping as $old_url => $new_url ) {
			$updated_content = str_replace( $old_url, $new_url, $updated_content );
		}

		return $updated_content;
	}

	/**
	 * Sanitize Gutenberg content while preserving block comments
	 *
	 * @param string $content Raw content
	 * @return string Sanitized content
	 */
	private function sanitize_gutenberg_content( $content ) {
		// For imported content from our own export, we need to preserve Gutenberg blocks
		// Use wp_unslash to handle any slashing, then basic sanitization without stripping comments
		$content = wp_unslash( $content );
		
		// Remove any potentially dangerous scripts but keep Gutenberg block structure
		$content = preg_replace( '/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/mi', '', $content );
		$content = preg_replace( '/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/mi', '', $content );
		
		// Basic XSS protection while preserving block comments
		$content = str_replace( array( 'javascript:', 'vbscript:', 'onload=', 'onerror=' ), '', $content );
		
		return $content;
	}

	/**
	 * Check for missing images in post data
	 *
	 * @param array $post_data Post data
	 * @return array Missing image filenames
	 */
	private function check_missing_images( $post_data ) {
		$missing = array();

		// Check featured image
		if ( ! empty( $post_data['featured_image']['filename'] ) ) {
			$filename = $post_data['featured_image']['filename'];
			if ( ! $this->find_existing_attachment_by_filename( $filename ) ) {
				$missing[] = $filename;
			}
		}

		// Check content images
		if ( ! empty( $post_data['content_images'] ) ) {
			foreach ( $post_data['content_images'] as $image ) {
				if ( ! empty( $image['filename'] ) ) {
					$filename = $image['filename'];
					if ( ! $this->find_existing_attachment_by_filename( $filename ) ) {
						$missing[] = $filename;
					}
				}
			}
		}

		return array_unique( $missing );
	}

	/**
	 * Fix attachment metadata to ensure proper srcset generation
	 *
	 * @param int $attachment_id Attachment ID
	 */
	private function fix_attachment_meta( $attachment_id ) {
		$file_path = get_attached_file( $attachment_id );
		if ( ! $file_path ) {
			return;
		}

		$upload_dir = wp_upload_dir();
		$upload_base = rtrim( $upload_dir['basedir'], '/\\' );
		
		// Calculate correct relative path
		$relative_path = str_replace( $upload_base, '', $file_path );
		$relative_path = ltrim( $relative_path, '/\\' );
		$relative_path = str_replace( DIRECTORY_SEPARATOR, '/', $relative_path );
		
		// Update the _wp_attached_file meta with correct path
		update_post_meta( $attachment_id, '_wp_attached_file', $relative_path );
		
		// Regenerate attachment metadata to fix srcset
		require_once ABSPATH . 'wp-admin/includes/image.php';
		$metadata = wp_generate_attachment_metadata( $attachment_id, $file_path );
		wp_update_attachment_metadata( $attachment_id, $metadata );
	}

	/**
	 * Download and create attachment from URL
	 *
	 * @param string $image_url Image URL
	 * @param int    $post_id Post ID
	 * @param string $image_title Image title
	 * @param string $image_alt Image alt text
	 * @return int|WP_Error|null Attachment ID or error
	 */
	private function download_and_create_attachment( $image_url, $post_id, $image_title = '', $image_alt = '' ) {
		$filename = basename( parse_url( $image_url, PHP_URL_PATH ) );
		
		// Record download attempt
		$this->import_results[] = array(
			'type' => 'download_start',
			'filename' => $filename,
			'url' => $image_url,
			'message' => 'Downloading image: ' . $filename,
		);

		// Add timeout and error handling for media_sideload_image
		add_filter( 'http_request_timeout', array( $this, 'set_import_timeout' ) );
		add_filter( 'http_request_args', array( $this, 'set_import_request_args' ) );
		
		$attachment_id = media_sideload_image( $image_url, $post_id, $image_title, 'id' );
		
		// Remove filters
		remove_filter( 'http_request_timeout', array( $this, 'set_import_timeout' ) );
		remove_filter( 'http_request_args', array( $this, 'set_import_request_args' ) );
		
		if ( is_wp_error( $attachment_id ) ) {
			// Record download failure
			$this->import_results[] = array(
				'type' => 'download_failed',
				'filename' => $filename,
				'url' => $image_url,
				'message' => 'Failed to download: ' . $filename . ' - ' . $attachment_id->get_error_message(),
			);
			return null; // Return null on failure
		}

		// Record download success
		$this->import_results[] = array(
			'type' => 'download_success',
			'filename' => $filename,
			'url' => $image_url,
			'attachment_id' => $attachment_id,
			'message' => 'Successfully downloaded: ' . $filename,
		);

		// Set alt text if provided
		if ( ! empty( $image_alt ) ) {
			update_post_meta( $attachment_id, '_wp_attachment_image_alt', $image_alt );
		}

		// Fix _wp_attached_file meta to ensure proper srcset generation
		$this->fix_attachment_meta( $attachment_id );

		return $attachment_id;
	}

	/**
	 * Get import results for detailed feedback
	 *
	 * @return array Import results
	 */
	private function get_import_results() {
		return $this->import_results;
	}

	/**
	 * Set import timeout for HTTP requests
	 *
	 * @param int $timeout Current timeout
	 * @return int New timeout
	 */
	public function set_import_timeout( $timeout ) {
		return 20; // 20 seconds timeout - reduced from 30
	}

	/**
	 * Set import request args for HTTP requests
	 *
	 * @param array $args Current args
	 * @return array Modified args
	 */
	public function set_import_request_args( $args ) {
		$args['timeout'] = 20; // Reduced from 30
		$args['redirection'] = 2; // Reduced from 3
		$args['httpversion'] = '1.1'; // Use HTTP/1.1 for better compatibility
		$args['blocking'] = true;
		$args['compress'] = true; // Enable compression
		return $args;
	}

	/**
	 * Resolve post author ID for import — fully backward compatible.
	 *
	 * Behavior matrix:
	 *
	 * | post_author_data present | User found by login/email | Result                      |
	 * |--------------------------|---------------------------|-----------------------------|
	 * | Yes                      | Yes                       | Matched user's ID           |
	 * | Yes                      | No + fallback=create_user | Create user, return new ID  |
	 * | Yes                      | No + fallback=current_user| Current logged-in admin ID  |
	 * | No (old export)          | ID exists on this site    | Use original ID as-is       |
	 * | No (old export)          | ID missing on this site   | Current logged-in admin ID  |
	 *
	 * @param int        $original_id  Raw post_author value from exported JSON.
	 * @param array|null $author_data  post_author_data block, or null if old export.
	 * @param string     $fallback     'current_user' or 'create_user'.
	 * @return int Valid WordPress user ID to use for the imported post.
	 */
	private function resolve_post_author( $original_id, $author_data, $fallback = 'current_user' ) {

		// ── NEW EXPORT: has identity data ──────────────────────────────────────
		if ( ! empty( $author_data ) && is_array( $author_data ) ) {

			// Try user_login first — unique per site, most reliable
			if ( ! empty( $author_data['user_login'] ) ) {
				$user = get_user_by( 'login', sanitize_user( $author_data['user_login'] ) );
				if ( $user instanceof WP_User ) {
					return absint( $user->ID );
				}
			}

			// Try user_email second — also unique per site
			if ( ! empty( $author_data['user_email'] ) ) {
				$user = get_user_by( 'email', sanitize_email( $author_data['user_email'] ) );
				if ( $user instanceof WP_User ) {
					return absint( $user->ID );
				}
			}

			// Author not found on this site — apply chosen fallback
			if ( 'create_user' === $fallback ) {
				$new_id = $this->create_imported_user( $author_data );
				if ( $new_id > 0 ) {
					return $new_id;
				}
			}

			// Default: assign to currently logged-in admin
			return absint( get_current_user_id() );
		}

		// ── OLD EXPORT: no identity data, only a raw ID ────────────────────────
		// Use the original ID only if that user actually exists on this site.
		if ( $original_id > 0 && false !== get_userdata( $original_id ) ) {
			return $original_id;
		}

		// Original ID does not exist on this site — silently assign to current admin.
		return absint( get_current_user_id() );
	}

	/**
	 * Create a WordPress user from imported author data.
	 *
	 * Uses the plugin's configured default password if set, otherwise generates
	 * a secure random password. Optionally sends a welcome email.
	 * Logs email send results to a transient for the import summary.
	 *
	 * @param array $author_data Author identity array from post_author_data.
	 * @return int New user ID on success, 0 on failure.
	 */
	private function create_imported_user( $author_data ) {

		$user_login   = sanitize_user( $author_data['user_login'] ?? '', true );
		$user_email   = sanitize_email( $author_data['user_email'] ?? '' );
		$display_name = sanitize_text_field( $author_data['display_name'] ?? '' );
		$role         = sanitize_text_field( $author_data['role'] ?? 'subscriber' );

		// Validate required fields
		if ( empty( $user_login ) || empty( $user_email ) || ! is_email( $user_email ) ) {
			return 0;
		}

		// Whitelist the role to only valid WordPress roles
		$valid_roles = array_keys( wp_roles()->get_names() );
		if ( ! in_array( $role, $valid_roles, true ) ) {
			$role = 'subscriber';
		}

		// Determine password — priority:
		// 1) Plugin default password if configured (admin setting)
		// 2) Exported password hash if present in author data
		// 3) Auto-generate secure random password
		$default_password = get_option( 'peiwm_user_import_default_password', '' );
		$use_hash         = false;

		if ( ! empty( $default_password ) ) {
			$password = $default_password;
		} elseif ( ! empty( $author_data['user_pass_hash'] )
		           && preg_match( '/^\$(?:P\$|wp\$|2y\$)/', $author_data['user_pass_hash'] ) ) {
			// Will use hash directly after creation — use temp password for wp_create_user
			$password = wp_generate_password( 24, true, true );
			$use_hash = true;
		} else {
			$password = wp_generate_password( 16, true, true );
		}

		// Attempt to create user with original login
		$user_id = wp_create_user( $user_login, $password, $user_email );

		// If login is taken, try a derived fallback login
		if ( is_wp_error( $user_id ) ) {
			$fallback_login = sanitize_user(
				substr( strstr( $user_email, '@', true ), 0, 20 ) . '_imported',
				true
			);
			$user_id = wp_create_user( $fallback_login, $password, $user_email );
		}

		// If still failing (e.g. email already exists), bail out
		if ( is_wp_error( $user_id ) ) {
			return 0;
		}

		wp_update_user( array(
			'ID'           => $user_id,
			'display_name' => $display_name,
			'role'         => $role,
		) );

		// Restore original password hash if applicable
		if ( $use_hash ) {
			global $wpdb;
			// phpcs:disable WordPress.DB.DirectDatabaseQuery
			$wpdb->update(
				$wpdb->users,
				array( 'user_pass' => sanitize_text_field( $author_data['user_pass_hash'] ) ),
				array( 'ID' => $user_id ),
				array( '%s' ),
				array( '%d' )
			);
			// phpcs:enable WordPress.DB.DirectDatabaseQuery
			clean_user_cache( $user_id );
		}

		// Send welcome email if option is enabled
		$send_email = (bool) get_option( 'peiwm_user_import_send_email', false );
		if ( $send_email ) {
			$site_name = sanitize_text_field( get_bloginfo( 'name' ) );
			$subject   = sprintf(
				/* translators: %s: site name */
				esc_html__( 'Your account on %s', 'post-export-import-with-media' ),
				$site_name
			);
			$message = sprintf(
				/* translators: 1: display name 2: username 3: password 4: login URL */
				esc_html__(
					"Hello %1\$s,\n\nYour account has been created.\n\nUsername: %2\$s\nPassword: %3\$s\n\nLogin at: %4\$s",
					'post-export-import-with-media'
				),
				$display_name,
				$user_login,
				$password,
				esc_url( wp_login_url() )
			);

			$sent      = wp_mail( $user_email, $subject, $message );
			$email_log = get_transient( 'peiwm_email_log' );
			$email_log = is_array( $email_log ) ? $email_log : array();
			$email_log[] = array(
				'email' => $user_email,
				'sent'  => $sent,
			);
			set_transient( 'peiwm_email_log', $email_log, HOUR_IN_SECONDS );
		}

		return absint( $user_id );
	}


}