<?php
/**
 * Preview Service
 *
 * @category   WordPress_Plugin
 * @package    Common
 * @subpackage Services\Preview
 * @author     miniOrange <info@miniorange.com>
 * @license    MIT/Expat
 * @link       https://plugins.miniorange.com/woocommerce-api-product-sync-with-woocommerce-rest-apis
 */

namespace MOWCPS\Common\Services\Preview;

use WP_Error;
use MOWCPS\Common\Models\Connection_Model;
use MOWCPS\Common\Models\Attribute_Mapping_Model;
use MOWCPS\Common\Models\Setting_Model;
use MOWCPS\Common\Models\Supplier_Model;
use MOWCPS\Common\Handlers\ConnectExternalSupplierHandler\Connect_External_Supplier_Handler;
use MOWCPS\Common\Handlers\ConnectExternalSupplierHandler\Connect_FTP_Handler;
use MOWCPS\Common\Utils\Sync_Utils;
use MOWCPS\Common\Constants\Constants;
use MOWCPS\Common\Constants\Plugin_Filters;
use MOWCPS\Common\Services\Logging\Supplier_Logger;
use MOWCPS\Common\Models\Sync_Details_DAO;
use MOWCPS\Common\Services\FTP\FTP_Service;
use MOWCPS\Common\Services\ReadFileData\Read_File_Data;

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

/**
 * Class Preview_Service
 *
 * Handles product preview operations including fetching and formatting
 */
class Preview_Service {

	/**
	 * Supplier ID
	 *
	 * @var int
	 */
	private $supplier_id;

	/**
	 * Primary connection ID
	 *
	 * @var int
	 */
	private $connection_id;

	/**
	 * Attribute mappings
	 *
	 * @var array
	 */
	private $attribute_mappings = array();

	/**
	 * Unique identifier field from connection
	 *
	 * @var string|null
	 */
	private $unique_identifier_field;

	/**
	 * Parent identifier field from connection
	 *
	 * @var string|null
	 */
	private $parent_identifier;

	/**
	 * Constructor
	 *
	 * @param int   $supplier_id Supplier ID.
	 * @param array $attribute_mapping_ids Array of attribute mapping UUIDs.
	 */
	public function __construct( $supplier_id, $attribute_mapping_ids = array() ) {
		$this->supplier_id = $supplier_id;
		$this->load_primary_connection();
		$this->load_unique_identifier_field();
		$this->load_attribute_mappings( $attribute_mapping_ids );
	}

	/**
	 * Load primary connection for the supplier
	 * For FILE suppliers, also try to get any FILE connection if no primary connection exists
	 *
	 * @return void
	 */
	private function load_primary_connection() {
		$connection = Connection_Model::get_primary_product_connection( $this->supplier_id );
		if ( ! empty( $connection['id'] ) ) {
			$this->connection_id = (int) $connection['id'];
			return;
		}

		// For FILE suppliers, try to get any FILE connection if no primary connection exists
		$supplier = Supplier_Model::get_by_id( $this->supplier_id );
		if ( ! $supplier ) {
			return;
		}

		$sync_type = $supplier['sync_type'] ?? '';
		if ( Constants::SYNC_TYPE_FILE === $sync_type ) {
			$all_connections = Connection_Model::get_by_supplier_id( $this->supplier_id );
			if ( is_array( $all_connections ) && ! empty( $all_connections ) ) {
				$first_connection    = reset( $all_connections );
				$this->connection_id = (int) $first_connection['id'];
				Supplier_Logger::debug( $this->supplier_id, 'No connection found, using FILE connection: ' . $this->connection_id );
			}
		}
	}

	/**
	 * Load unique identifier field from connection configuration
	 *
	 * @return void
	 */
	private function load_unique_identifier_field() {
		if ( empty( $this->connection_id ) ) {
			return;
		}

		$connection = Connection_Model::get_by_id( $this->connection_id );

		$prerequisites = $connection['configuration']['prerequisites'];

		if ( isset( $prerequisites['variable_response']['parent_identifier'] ) && ! empty( $prerequisites['variable_response']['parent_identifier'] ) ) {
			$this->parent_identifier = $prerequisites['variable_response']['parent_identifier'];
			Supplier_Logger::debug( $this->supplier_id, 'Using parent_identifier for deduplication: ' . $this->unique_identifier_field );
		}

		$this->unique_identifier_field = $prerequisites['main_product_unique_identifier'];
	}

	/**
	 * Load attribute mappings
	 *
	 * @param array $attribute_mapping_ids Array of attribute mapping UUIDs.
	 * @return void
	 */
	private function load_attribute_mappings( $attribute_mapping_ids ) {
		// Ensure attribute_mappings is always an array.
		$this->attribute_mappings = array();

		// If no connection_id, we can't load mappings, return empty array.
		if ( empty( $this->connection_id ) ) {
			Supplier_Logger::debug( $this->supplier_id, 'No connection_id available, cannot load attribute mappings' );
			return;
		}

		if ( empty( $attribute_mapping_ids ) ) {
			$this->attribute_mappings = Attribute_Mapping_Model::get_all(
				array(
					'supplier_id'   => $this->supplier_id,
					'connection_id' => $this->connection_id,
				)
			);
		} else {
			$mappings = array();
			foreach ( $attribute_mapping_ids as $uuid ) {
				$mapping = Attribute_Mapping_Model::get_by_uuid( $uuid );
				if ( $mapping && ! is_wp_error( $mapping ) ) {
					if ( isset( $mapping['connection_id'] ) && intval( $mapping['connection_id'] ) === intval( $this->connection_id ) ) {
						$mappings[] = $mapping;
					}
				}
			}
			$this->attribute_mappings = $mappings;
		}

		$mapping_override = apply_filters(
			Plugin_Filters::FILTER_PREVIEW_ATTRIBUTE_MAPPING,
			array(
				'override_mappings'  => false,
				'attribute_mappings' => array(),
				'supplier_id'        => $this->supplier_id,
			)
		);

		$this->attribute_mappings = $mapping_override['override_mappings'] && ! empty( $mapping_override['attribute_mappings'] ) ? $mapping_override['attribute_mappings'] : $this->attribute_mappings;
	}

	/**
	 * Fetch products from supplier API or File
	 *
	 * @param int $page Page number to fetch (for preview pagination, not API pagination).
	 * @return array|WP_Error Array of products or error
	 */
	public function fetch_products_from_api( $page = 1 ) {
		// Check if connection_id is set (should be set in constructor).
		if ( ! $this->connection_id ) {
			return new WP_Error(
				Constants::ERROR_CONNECTION_NOT_FOUND,
				'No primary connection found for this supplier',
				array( 'status' => Constants::HTTP_NOT_FOUND )
			);
		}

		// Check if attribute mappings are configured.
		if ( empty( $this->attribute_mappings ) || ! is_array( $this->attribute_mappings ) ) {
			return new WP_Error(
				Constants::ERROR_INVALID_SUPPLIER_CONFIG,
				'No attribute mappings found. Please configure attribute mappings before previewing products.',
				array( 'status' => Constants::HTTP_BAD_REQUEST )
			);
		}

		try {
			$connection_details = Connection_Model::get_by_id( $this->connection_id );
			$connection_type    = $connection_details['type'] ?? Constants::API_CONNECTION;

			Sync_Details_DAO::get_instance()->set_connection_details( $this->connection_id, $connection_details );

			$file_sync_details = Setting_Model::get_by_connection_and_operation( $this->connection_id, 'file-sync', array( 'configuration' => true ) );

			$is_active_flag = isset( $file_sync_details['is_active'] ) ? $file_sync_details['is_active'] : '0';
			$is_file_sync   = ( '1' === $is_active_flag ) || ( Constants::FTP_CONNECTION === $connection_type ) || ( Constants::CONNECTION_TYPE_FILE === $connection_type );

			if ( $is_file_sync ) {
				return $this->fetch_products_from_file( $page, $connection_type, $connection_details, $file_sync_details );
			}

			Supplier_Logger::debug( $this->supplier_id, "Fetching preview products from API (page: {$page})..." );

			$connect_handler = new Connect_External_Supplier_Handler( $this->connection_id, $this->supplier_id, $page );

			$api_response = $connect_handler->connect_api_handler( Constants::INBOUND_SYNC );

			if ( is_wp_error( $api_response ) ) {
				Supplier_Logger::debug( $this->supplier_id, 'ERROR: Failed to fetch preview products: ' . $api_response->get_error_message() );
				return $api_response;
			}

			$api_response = Sync_Utils::get_main_response_array( $api_response, $this->connection_id );

			$product_count = is_array( $api_response ) ? count( $api_response ) : 0;
			Supplier_Logger::debug( $this->supplier_id, "Fetched {$product_count} products from API" );

			return $api_response;

		} catch ( \Throwable $t ) {
			Supplier_Logger::debug(
				$this->supplier_id,
				'ERROR: Throwable while fetching preview products: ' . $t->getMessage() .
				' in ' . $t->getFile() . ':' . $t->getLine()
			);
			return new WP_Error(
				Constants::ERROR_GENERAL,
				'Failed to fetch products: ' . $t->getMessage(),
				array( 'status' => Constants::HTTP_INTERNAL_SERVER_ERROR )
			);
		}
	}

	/**
	 * Fetch products from file in batches (for FTP, file-sync, and FILE connection types)
	 * PREMIUM ONLY FEATURE
	 *
	 * @param int    $page                Preview page number.
	 * @param string $connection_type     Connection type (ftp/api/file).
	 * @param array  $connection_details  Connection details including configuration.
	 * @param array  $file_sync_details   File sync configuration (for FTP/API file-sync only).
	 * @return array|WP_Error Array of products or error
	 */
	private function fetch_products_from_file( $page, $connection_type, $connection_details, $file_sync_details = array() ) {
		$is_file_connection = ( Constants::CONNECTION_TYPE_FILE === $connection_type );

		$batch_size = 5000;
		Supplier_Logger::debug( $this->supplier_id, "Reading {$batch_size} rows from file (will be deduplicated to unique parents)" );

		// Determine configuration source based on connection type.
		$config_source = $is_file_connection ? ( $connection_details['configuration'] ?? array() ) : ( $file_sync_details['configuration'] ?? array() );

		// Extract common configuration values.
		$file_name = $config_source['file_name'] ?? '';
		$delimiter = $config_source['delimiter'] ?? '';

		// Set directory and file naming based on connection type.
		if ( $is_file_connection ) {
			$file_directory     = trailingslashit( MOWCPS_PLUGIN_DIR ) . 'data' . DIRECTORY_SEPARATOR . 'external-supplier' . DIRECTORY_SEPARATOR . 'file-response';
			$file_type          = $config_source['file_type'] ?? '';
			$complete_file_name = $file_name . '.' . $file_type;
			$has_header         = ! empty( $config_source['use_first_row_as_header'] );
		} else {
			$file_directory     = trailingslashit( MOWCPS_PLUGIN_DIR ) . 'data' . DIRECTORY_SEPARATOR . 'external-supplier' . DIRECTORY_SEPARATOR . 'api-file-response' . DIRECTORY_SEPARATOR . $this->connection_id;
			$complete_file_name = $file_name;
			$file_in_zip        = $config_source['is_zip'] ?? false;
			$has_header         = true; // FTP/API file-sync always assumes header on line 1.
		}

		$file_path = $file_directory . DIRECTORY_SEPARATOR . $complete_file_name;

		// Download file if needed (only for FTP/API file-sync, not for FILE connections).
		if ( ! $is_file_connection && ( ! file_exists( $file_path ) || 1 === $page ) ) {
			Supplier_Logger::debug( $this->supplier_id, 'File not found or first page - downloading file...' );

			if ( Constants::FTP_CONNECTION === $connection_type ) {
				$connect_external_supplier_handler = new Connect_FTP_Handler( $this->connection_id, $this->supplier_id );
				$file_response                     = $connect_external_supplier_handler->connect_ftp_handler( $this->connection_id, $this->supplier_id );

				if ( is_wp_error( $file_response ) || empty( $file_response ) ) {
					Supplier_Logger::debug( $this->supplier_id, 'ERROR: FTP download failed' );
					return new WP_Error(
						Constants::ERROR_GENERAL,
						'Failed to download file from FTP',
						array( 'status' => Constants::HTTP_INTERNAL_SERVER_ERROR )
					);
				}
			} else {
				$connect_handler = new Connect_External_Supplier_Handler( $this->connection_id, $this->supplier_id, 1 );
				$api_response    = $connect_handler->connect_api_handler( Constants::INBOUND_SYNC );

				if ( is_wp_error( $api_response ) ) {
					return $api_response;
				}

				$connect_external_supplier_handler = new Connect_FTP_Handler( $this->connection_id, $this->supplier_id );
				$file_response                     = $connect_external_supplier_handler->file_from_api_handler( $this->connection_id, $file_name, $file_in_zip, $api_response );

				if ( is_wp_error( $file_response ) || empty( $file_response ) ) {
					Supplier_Logger::debug( $this->supplier_id, 'ERROR: File download from API failed' );
					return new WP_Error(
						Constants::ERROR_GENERAL,
						'Failed to download file from API',
						array( 'status' => Constants::HTTP_INTERNAL_SERVER_ERROR )
					);
				}
			}

			Supplier_Logger::debug( $this->supplier_id, 'File downloaded successfully' );
		}

		// Check if file exists (for FILE connections, file should already be uploaded).
		if ( $is_file_connection && ( ! file_exists( $file_path ) || ! is_readable( $file_path ) ) ) {
			Supplier_Logger::debug( $this->supplier_id, 'ERROR: Uploaded file not found or not readable: ' . $complete_file_name );
			return new WP_Error(
				Constants::ERROR_GENERAL,
				'Uploaded file not found. Please ensure the file has been uploaded.',
				array( 'status' => Constants::HTTP_NOT_FOUND )
			);
		}

		// Read file data based on connection type
		if ( $is_file_connection ) {
			$products = $this->read_uploaded_file_data( $file_directory, $complete_file_name, $page, $batch_size, $has_header, $delimiter );
		} else {
			$products = $this->read_ftp_file_data( $file_directory, $complete_file_name, $page, $batch_size, $delimiter );
		}

		if ( empty( $products ) || ! is_array( $products ) ) {
			Supplier_Logger::debug( $this->supplier_id, 'No more data in file or end reached' );
			return array();
		}

		Supplier_Logger::debug( $this->supplier_id, 'Returning ' . count( $products ) . ' products from file' );

		return $products;
	}

	/**
	 * Read products from uploaded FILE connection
	 *
	 * Uses Read_File_Data service which handles header inclusion automatically.
	 * Read_File_Data uses 1-based indexing for data rows.
	 * If has_header=true, header is on line 1, data starts at line 2.
	 *
	 * @param string $file_directory    Directory containing the file.
	 * @param string $complete_file_name Full file name with extension.
	 * @param int    $page              Preview page number.
	 * @param int    $batch_size        Number of rows to read per batch.
	 * @param bool   $has_header        Whether file has header row.
	 * @param string $delimiter         File delimiter.
	 * @return array Array of products (directly from Read_File_Data, not wrapped).
	 */
	private function read_uploaded_file_data( $file_directory, $complete_file_name, $page, $batch_size, $has_header, $delimiter ) {
		// Read_File_Data uses 1-based indexing for data rows
		// If has_header=true, header is on line 1, data starts at line 2
		$start_line = 1 + ( ( $page - 1 ) * $batch_size );
		$end_line   = $start_line + $batch_size - 1;

		$batch = Read_File_Data::read_data_from_file(
			$file_directory,
			$complete_file_name,
			$start_line,
			$end_line,
			$has_header,
			$delimiter
		);

		// FILE connections return data directly (not wrapped in main_response_array)
		return $batch;
	}

	/**
	 * Read products from FTP/API file-sync connection
	 *
	 * Uses FTP_Service which requires reading header separately (line 1) and data separately.
	 * Header is always on line 1, product data starts at line 2.
	 * Requires get_main_response_array processing to format the data.
	 *
	 * @param string $file_directory    Directory containing the file.
	 * @param string $complete_file_name Full file name with extension.
	 * @param int    $page              Preview page number.
	 * @param int    $batch_size        Number of rows to read per batch.
	 * @param string $delimiter         File delimiter.
	 * @return array Array of products (processed through get_main_response_array).
	 */
	private function read_ftp_file_data( $file_directory, $complete_file_name, $page, $batch_size, $delimiter ) {
		// FTP_Service always reads header separately (line 1) and data separately
		// Header is on line 1, product data starts at line 2
		$first_product_line = 2 + ( ( $page - 1 ) * $batch_size );
		$last_product_line  = $first_product_line + $batch_size - 1;

		$header_batch  = FTP_Service::read_data_from_file( $file_directory, $complete_file_name, 1, 1, $delimiter );
		$product_batch = FTP_Service::read_data_from_file( $file_directory, $complete_file_name, $first_product_line, $last_product_line, $delimiter );

		$batch = array_merge( $header_batch ?? array(), $product_batch ?? array() );

		// FTP/API file-sync needs get_main_response_array to format the data
		return Sync_Utils::get_main_response_array( $batch, $this->connection_id );
	}

	/**
	 * Format products with selected attributes
	 *
	 * @param array $api_products Raw products from API.
	 * @return array Formatted products
	 */
	public function format_products( $api_products ) {
		if ( empty( $api_products ) || ! is_array( $api_products ) ) {
			return array();
		}

		$formatted_products           = array();
		$processed_parent_identifiers = array();

		foreach ( $api_products as $product ) {
			$formatted_product    = array();
			$processed_attributes = array();

			$formatted_product['_raw_product'] = $product;

			if ( ! empty( $this->unique_identifier_field ) || '0' === $this->unique_identifier_field ) {
				if ( ! empty( $this->parent_identifier ) || '0' === $this->parent_identifier ) {
					$unique_id_value = Sync_Utils::map_particular_attr( $this->parent_identifier, $product, '' );
				} else {
					$unique_id_value = Sync_Utils::map_particular_attr( $this->unique_identifier_field, $product, '' );
				}

				if ( is_array( $unique_id_value ) || is_object( $unique_id_value ) ) {
					$unique_id_value = Constants::NO_PREVIEW_AVAILABLE;
				} else {
					$unique_id_value = (string) $unique_id_value;
					if ( ! empty( $unique_id_value ) ) {
						$unique_id_value = $this->strip_html_tags( $unique_id_value );
					}
				}

				if ( in_array( $unique_id_value, $processed_parent_identifiers, true ) ) {
					Supplier_Logger::debug( $this->supplier_id, "Skipping duplicate parent product with unique_identifier: {$unique_id_value}" );
					continue;
				}

				$formatted_product['unique_identifier']    = $unique_id_value;
				$processed_attributes['unique_identifier'] = true;
				$processed_parent_identifiers[]            = $unique_id_value;
			}

			foreach ( $this->attribute_mappings as $mapping ) {
				if ( 'parent' !== $mapping['product_type'] ) {
					continue;
				}

				$wc_attribute       = $mapping['wc_attribute'];
				$supplier_attribute = $mapping['supplier_attribute'];

				if ( isset( $processed_attributes[ $wc_attribute ] ) ) {
					continue;
				}

				if ( 'images' === $wc_attribute ) {
					$values = explode( ',', $supplier_attribute );
					if ( ! empty( $values ) ) {
						$supplier_attribute = $values[0];
					}
				}
				$value = Sync_Utils::map_particular_attr( $supplier_attribute, $product, '' );

				if ( 'images' === $wc_attribute ) {
					$value = $this->extract_first_image( $value, $mapping );
				}

				if ( is_array( $value ) || is_object( $value ) ) {
					$value = Constants::NO_PREVIEW_AVAILABLE;
				} else {
					$value = (string) $value;

					if ( ! empty( $value ) && 'images' !== $wc_attribute ) {
						$value = $this->strip_html_tags( $value );
					}
				}

				$formatted_product[ $wc_attribute ]    = $value;
				$processed_attributes[ $wc_attribute ] = true;
			}

			$formatted_products[] = $formatted_product;
		}

		return $formatted_products;
	}

	/**
	 * Get pagination information
	 *
	 * @param int $current_page Current API page.
	 * @return array Pagination details
	 */
	public function get_pagination_info( $current_page = 1 ) {
		$page_settings = Setting_Model::get_by_connection_and_operation(
			$this->connection_id,
			'page',
			array( 'configuration' => true )
		);

		$has_pagination = ! empty( $page_settings['is_active'] ) && '1' === (string) $page_settings['is_active'];

		return array(
			'has_pagination' => $has_pagination,
			'current_page'   => $current_page,
			'page_config'    => $has_pagination ? $page_settings['configuration'] : array(),
		);
	}

	/**
	 * Get attribute mappings for column display
	 *
	 * @return array Array of attribute labels and keys
	 */
	public function get_column_definitions() {
		$columns    = array();
		$added_keys = array();

		if ( ! empty( $this->unique_identifier_field ) || '0' === $this->unique_identifier_field ) {
			$columns[]                       = array(
				'key'   => 'unique_identifier',
				'label' => 'Unique Identifier',
				'type'  => 'core',
			);
			$added_keys['unique_identifier'] = true;
		}

		foreach ( $this->attribute_mappings as $mapping ) {
			if ( 'parent' !== $mapping['product_type'] ) {
				continue;
			}

			$wc_attribute = $mapping['wc_attribute'];

			if ( isset( $added_keys[ $wc_attribute ] ) ) {
				Supplier_Logger::debug( $this->supplier_id, "Skipping duplicate column: {$wc_attribute}" );
				continue;
			}
			$type                        = isset( $mapping['type'] ) ? $mapping['type'] : '';
			$columns[]                   = array(
				'key'   => $wc_attribute,
				'label' => $this->get_attribute_label( $wc_attribute, $type ),
				'type'  => $type,
			);
			$added_keys[ $wc_attribute ] = true;
		}

		$unique_id_column = null;
		$other_columns    = array();

		foreach ( $columns as $column ) {
			if ( 'unique_identifier' === $column['key'] ) {
				$unique_id_column = $column;
			} else {
				$other_columns[] = $column;
			}
		}

		usort(
			$other_columns,
			function ( $a, $b ) {
				$priority_order = array(
					'images'      => 1,
					'sku'         => 2,
					'name'        => 3,
					'description' => 4,
				);
				$priority_a     = isset( $priority_order[ $a['key'] ] ) ? $priority_order[ $a['key'] ] : 999;
				$priority_b     = isset( $priority_order[ $b['key'] ] ) ? $priority_order[ $b['key'] ] : 999;
				return $priority_a - $priority_b;
			}
		);

		$final_columns = array();
		if ( $unique_id_column ) {
			$final_columns[] = $unique_id_column;
		}
		$final_columns = array_merge( $final_columns, $other_columns );

		return $final_columns;
	}

	/**
	 * Get human-readable label for attribute
	 *
	 * @param string $wc_attribute WooCommerce attribute key.
	 * @param string $type Attribute type.
	 * @return string Human-readable label
	 */
	private function get_attribute_label( $wc_attribute, $type ) {
		$label_map = array(
			'sku'              => 'SKU',
			'name'             => 'Name',
			'description'      => 'Description',
			'regular_price'    => 'Price',
			'sale_price'       => 'Sale Price',
			'stock_quantity'   => 'Stock',
			'images'           => 'Image',
			'product_category' => 'Category',
			'product_tag'      => 'Tags',
			'product_brand'    => 'Brand',
		);

		if ( isset( $label_map[ $wc_attribute ] ) ) {
			return $label_map[ $wc_attribute ];
		}

		return ucwords( str_replace( array( '_', '-' ), ' ', $wc_attribute ) );
	}

	/**
	 * Extract first image from various image data formats
	 *
	 * @param mixed $value   Image data from API.
	 * @param array $mapping Attribute mapping configuration.
	 * @return string Image URL or empty string
	 */
	private function extract_first_image( $value, $mapping ) {
		$image_path_attr = isset( $mapping['advanced_configuration']['image_path_attr'] ) ? trim( $mapping['advanced_configuration']['image_path_attr'] ) : '';
		if ( is_string( $value ) && ! empty( $value ) ) {
			if ( ! empty( $image_path_attr ) ) {
				$image_path_attr = rtrim( $image_path_attr, '/' );
				$value           = ltrim( $value, '/' );
				$value           = $image_path_attr . '/' . $value;
			}
			if ( filter_var( $value, FILTER_VALIDATE_URL ) || strpos( $value, '/' ) !== false ) {
				return $value;
			}
		}

		if ( ! is_array( $value ) ) {
			return '';
		}

		$image_src_attr = isset( $mapping['advanced_configuration']['image_src_attr'] ) ? $mapping['advanced_configuration']['image_src_attr'] : 'src';

		if ( empty( $value ) ) {
			return '';
		}

		$first_image = $value[0];

		if ( is_array( $first_image ) ) {
			$value = Sync_Utils::map_particular_attr( $image_src_attr, $first_image, '' );
			if ( ! empty( $image_path_attr ) ) {
				$image_path_attr = rtrim( $image_path_attr, '/' );
				$value           = ltrim( $value, '/' );

				return $image_path_attr . '/' . $value;
			}
			return $value;
		}

		if ( is_string( $first_image ) ) {
			$value = $first_image;
			if ( ! empty( $image_path_attr ) ) {
				$image_path_attr = rtrim( $image_path_attr, '/' );
				$value           = ltrim( $value, '/' );

				return $image_path_attr . '/' . $value;
			}
			return $value;
		}

		if ( is_object( $first_image ) ) {
			$first_image = (array) $first_image;
			if ( isset( $first_image[ $image_src_attr ] ) ) {
				$value = $first_image[ $image_src_attr ];
				if ( ! empty( $image_path_attr ) ) {
					$image_path_attr = rtrim( $image_path_attr, '/' );
					$value           = ltrim( $value, '/' );

					return $image_path_attr . '/' . $value;
				}
				return $value;
			}
		}

		return '';
	}

	/**
	 * Strip HTML tags and clean text for display
	 *
	 * @param string $text Text that may contain HTML.
	 * @return string Cleaned text
	 */
	private function strip_html_tags( $text ) {
		$text = html_entity_decode( $text, ENT_QUOTES | ENT_HTML5, 'UTF-8' );
		$text = wp_strip_all_tags( $text );
		$text = preg_replace( '/\s+/', ' ', $text );
		$text = trim( $text );
		return $text;
	}
}
