<?php
/**
 * Pdf main class file.
 *
 * This class handles all PDF-related functionality including file uploads,
 * DOCX processing, smart tag extraction, and PDF conversion.
 *
 * @since 1.9.0
 * @package sureforms-pro
 */

namespace SRFM_Pro\Inc\Business\Pdf;

use SRFM\Inc\Helper;

// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;

/**
 * Load Pdf feature related functionalities.
 *
 * This class provides methods for handling PDF operations including:
 * - File uploads and processing
 * - Smart tag extraction from DOCX files
 * - PDF conversion and generation
 * - Template processing with smart tags
 *
 * @since 1.9.0
 */
class Utils {
	/**
	 * Process the pdf link.
	 *
	 * @param string $confirmation_message The confirmation message.
	 * @param array  $form_data Form submission data.
	 * @param array  $submission_data Additional submission data.
	 *
	 * @since 1.9.0
	 * @return string Modified confirmation message.
	 */
	public static function process_pdf_link( $confirmation_message, $form_data, $submission_data ) {
		if ( ! self::check_if_library_exists() ) {
			return $confirmation_message;
		}

		// Get the smart tags in the confirmation message.
		$smart_tags = self::get_the_pdf_smart_tags( $confirmation_message );

		// If smart tags is empty then return the confirmation message.
		if ( empty( $smart_tags ) ) {
			return $confirmation_message;
		}

		$pdf_as_slug = self::pdf_meta_with_slug_index( $form_data );

		$processed_pdf = [];

		// Loop through the smart tags and get the pdf meta data.
		foreach ( $smart_tags as $smart_tag ) {
			// Check $smart_tag is string.
			if ( ! is_string( $smart_tag ) ) {
				continue;
			}

			// get the pdf item from the pdf_as_slug.
			$pdf_item = $pdf_as_slug[ $smart_tag ] ?? [];

			$pdf_processed = '';
			if ( ! empty( $pdf_item ) && is_array( $pdf_item ) ) {
				$pdf_processed = Document::process_pdf_item( $pdf_item, $form_data, $submission_data, $smart_tag );
			}

			$processed_pdf[ $smart_tag ] = [
				'pdf_link' => $pdf_processed,
				'pdf_item' => $pdf_item,
			];
		}

		// Replace the smart tag with the pdf link in the all the smart tags. pdf link will be the link and item name will be the text.
		foreach ( $processed_pdf as $smart_tag => $pdf_link ) {
			$pdf_link_html = '';

			// if the pdf link and pdf item is not empty then create the pdf link html.
			if ( ! empty( $pdf_link['pdf_link'] ) && ! empty( $pdf_link['pdf_item'] ) ) {
				$pdf_item_name = $pdf_link['pdf_item']['generic']['name'] ?? __( 'Download PDF', 'sureforms-pro' );
				ob_start();
				?>
				<a href="<?php echo esc_url( $pdf_link['pdf_link'] ); ?>" target="_blank" rel="noopener noreferrer"><?php echo esc_html( $pdf_item_name ); ?></a>
				<?php
				$pdf_link_html = ob_get_clean();
				$pdf_link_html = is_string( $pdf_link_html ) ? trim( $pdf_link_html ) : '';
			}

			$confirmation_message = str_replace( $smart_tag, $pdf_link_html, $confirmation_message );
		}

		return $confirmation_message;
	}

	/**
	 * Get the PDF file directory path.
	 *
	 * Returns the absolute path to the directory where PDF files are stored.
	 * Creates the directory if it doesn't exist.
	 *
	 * @param string $url_type The type of URL to return. either 'path' or 'url'.
	 *
	 * @since 1.9.0
	 * @return string Absolute path to the PDF storage directory
	 */
	public static function pdf_file_dir( $url_type = 'path' ) {
		$upload_dir = wp_upload_dir();
		if ( 'path' === $url_type ) {
			return $upload_dir['basedir'] . '/sureforms/pdfs';
		}
		return $upload_dir['baseurl'] . '/sureforms/pdfs';
	}

	/**
	 * Convert PDF metadata array to a slug-indexed array for easier lookup.
	 *
	 * Takes an array of PDF metadata items and restructures it into an associative array
	 * where each item is indexed by its slug wrapped in curly braces for smart tag usage.
	 * For example, a slug "invoice" becomes "{invoice}" as the array key.
	 *
	 * @param array $form_data Form data containing form ID and other form information.
	 * @return array Associative array with smart tag slugs as keys (e.g. {slug}) and full metadata items as values.
	 *               Returns empty array if no valid PDF metadata is found.
	 * @since 1.9.0
	 */
	public static function pdf_meta_with_slug_index( $form_data ) {
		// Check for the form-id in the form data.
		if ( empty( $form_data['form-id'] ) ) {
			return [];
		}

		// Extract the form ID from form data and ensure it's an integer.
		$form_id = Helper::get_integer_value( $form_data['form-id'] );

		// Retrieve the raw PDF metadata from WordPress post meta.
		$pdf_meta = get_post_meta( $form_id, '_srfm_pdf_meta', true );

		// Return empty array if metadata is empty or not a string.
		if ( empty( $pdf_meta ) || ! is_string( $pdf_meta ) ) {
			return [];
		}

		// Decode the JSON metadata string into an array.
		$pdf_meta = json_decode( $pdf_meta, true );

		// Return empty array if JSON decode failed or result is not an array.
		if ( empty( $pdf_meta ) || ! is_array( $pdf_meta ) ) {
			return [];
		}

		// Initialize array to store PDF metadata indexed by smart tag slugs.
		$pdf_by_slug = [];

		// Process each PDF metadata item.
		foreach ( $pdf_meta as $item ) {
			// Skip items with invalid or missing slugs.
			if ( empty( $item['slug'] ) || ! is_string( $item['slug'] ) ) {
				continue;
			}

			// Skip if item is not an array.
			if ( ! is_array( $item ) ) {
				continue;
			}

			// Convert slug to smart tag format by wrapping in curly braces.
			$slug_with_curl_brackets = '{' . $item['slug'] . '}';

			// Store the full metadata item indexed by its smart tag slug.
			$pdf_by_slug[ $slug_with_curl_brackets ] = $item;
		}

		return $pdf_by_slug;
	}

	/**
	 * Get the pdf smart tags from the content.
	 *
	 * @param string $content The content to get the pdf smart tags from.
	 *
	 * @since 1.9.0
	 * @return array
	 */
	public static function get_the_pdf_smart_tags( $content ) {
		preg_match_all( '/{pdf:.*?}/', $content, $matches );

		if ( empty( $matches[0] ) ) {
			return [];
		}

		if ( ! is_array( $matches[0] ) ) {
			return [];
		}

		return array_unique( $matches[0] );
	}

	/**
	 * Filter and sanitize PDF meta data.
	 * Removes custom templates where the file doesn't exist.
	 *
	 * @param mixed $meta_value The meta value to filter.
	 *
	 * @since 1.9.0
	 * @return mixed Filtered meta value.
	 */
	public static function filter_pdf_meta_retrieval( $meta_value ) {
		// If value is empty or not a string, return as is.
		if ( empty( $meta_value ) || ! is_string( $meta_value ) ) {
			return $meta_value;
		}

		$decoded_value = json_decode( $meta_value, true );
		if ( ! is_array( $decoded_value ) ) {
			return $meta_value;
		}

		// Filter and process templates.
		$filtered_data = [];
		foreach ( $decoded_value as $item ) {
			// Keep generic templates as is.
			if ( isset( $item['templateType'] ) && 'generic' === $item['templateType'] ) {
				$filtered_data[] = $item;
				continue;
			}

			$filtered_data[] = $item;
		}

		// Re-index array after filtering.
		return wp_json_encode( array_values( $filtered_data ) );
	}

	/**
	 * Custom array sanitizer.
	 * This function is used to sanitize the array data before saving it as post meta. check the context file for the structure.
	 *
	 * @param string $pdf_content The pdf content to sanitize.
	 *
	 * @since 1.9.0
	 * @return string
	 */
	public static function pdf_array_sanitizer( $pdf_content ) {
		// Decode the array.
		$pdf_content = self::escape_style_quotes_for_json( $pdf_content );

		if ( empty( $pdf_content ) || ! is_array( $pdf_content ) ) {
			return '';
		}

		$sanitized = [];

		foreach ( $pdf_content as $template ) {
			$sanitized_template = [
				'templateType' => isset( $template['templateType'] ) ? sanitize_text_field( $template['templateType'] ) : '',
				'status'       => isset( $template['status'] ) ? (bool) $template['status'] : false,
				'slug'         => isset( $template['slug'] ) ? sanitize_text_field( $template['slug'] ) : '',
				'generic'      => [],
			];

			// Sanitize 'generic' section.
			if ( isset( $template['generic'] ) && is_array( $template['generic'] ) ) {
				$sanitized_template['generic'] = [
					'name'             => isset( $template['generic']['name'] ) ? sanitize_text_field( $template['generic']['name'] ) : '',
					'paperSize'        => isset( $template['generic']['paperSize'] ) ? sanitize_text_field( $template['generic']['paperSize'] ) : '',
					// Note: i need to sanitize the pdfContent when remove the js stripper available.
					'pdfContent'       => $template['generic']['pdfContent'] ?? '',
					'paperOrientation' => isset( $template['generic']['paperOrientation'] ) ? sanitize_text_field( $template['generic']['paperOrientation'] ) : '',
					'pdfPassword'      => isset( $template['generic']['pdfPassword'] ) ? sanitize_text_field( $template['generic']['pdfPassword'] ) : '',
				];
			}

			$sanitized[] = $sanitized_template;
		}

		// Return final sanitized string.
		$sanitized_pdf_content = wp_json_encode( $sanitized, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );

		return $sanitized_pdf_content ? $sanitized_pdf_content : '';
	}

	/**
	 * Escapes double quotes inside HTML style attributes for proper JSON decoding.
	 *
	 * @param string $json_string The JSON string containing HTML with style attributes.
	 *
	 * @since 1.9.0
	 * @return array The corrected JSON array with escaped quotes.
	 */
	public static function escape_style_quotes_for_json( $json_string ) {
		if ( empty( $json_string ) || ! is_string( $json_string ) ) {
			return [];
		}

		// Regex: Matches style="..." but ignores style=\"...\" (already escaped).
		$pattern     = '/style="([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"/';
		$replacement = 'style=\"$1\"';

		// in the content there is "\n" so i need to remove that also.
		$json_string = str_replace( '\n', '', $json_string );

		$replaced_content = preg_replace( $pattern, $replacement, $json_string );

		if ( empty( $replaced_content ) || ! is_string( $replaced_content ) ) {
			return [];
		}

		$pdf_meta = json_decode( $replaced_content, true );
		if ( ! is_array( $pdf_meta ) ) {
			return [];
		}

		return $pdf_meta;
	}

	/**
	 * Check if the library exists.
	 *
	 * @since 1.9.0
	 * @return bool
	 */
	public static function check_if_library_exists() {
		$plugin_dir = WP_PLUGIN_DIR . '/sureforms-libraries/pdf';
		$vendor_dir = $plugin_dir . '/vendor/autoload.php';

		if ( ! file_exists( $vendor_dir ) ) {
			return false;
		}

		return true;
	}

	/**
	 * Add PDF link in entry.
	 *
	 * @param array $args The arguments.
	 *
	 * @since 1.9.0
	 * @return array
	 */
	public static function process_pdf_link_in_entry( $args ) {
		$form_data       = $args['form_data'] ?? [];
		$submission_data = $args['submission_data'] ?? [];

		if ( empty( $form_data ) || empty( $submission_data ) ) {
			return [];
		}

		$form_id = Helper::get_integer_value( $form_data['form-id'] );

		$pdf_meta = get_post_meta( $form_id, '_srfm_pdf_meta', true );

		if ( empty( $pdf_meta ) || ! is_string( $pdf_meta ) ) {
			return [];
		}

		$pdf_meta = json_decode( $pdf_meta, true );

		if ( empty( $pdf_meta ) || ! is_array( $pdf_meta ) ) {
			return [];
		}

		$pdf_links_key_array = [];

		foreach ( $pdf_meta as $item ) {
			if ( ! is_array( $item ) ) {
				continue;
			}

			// Check if the item is a valid pdf item. both slug and status are required.
			if ( empty( $item['slug'] ) || empty( $item['status'] ) ) {
				continue;
			}

			$pdf_name                = $item['generic']['name'] ?? '';
			$slug_with_curl_brackets = '{' . $item['slug'] . '}';

			$pdf_links_key_array[ $pdf_name ] = Document::process_pdf_item( $item, $form_data, $submission_data, $slug_with_curl_brackets );
		}

		if ( empty( $pdf_links_key_array ) ) {
			return [];
		}

		return $pdf_links_key_array;
	}

	/**
	 * Get the editor default styles.
	 * This is the default styles for the editors (tinymce, mpdf editor ).
	 *
	 * @since 1.9.0
	 * @return string
	 */
	public static function editor_default_styles() {
		return 'body {
						font-family: \'figtree\', sans-serif;
						font-size: 14px;
						color: #111827;
						line-height: 1.2;
					}
					h1, h2, h3, h4, h5, h6 {
						margin: 10px 0;
						color: #111827;
					}
					h1 { font-size: 32px; }
					h2 { font-size: 28px; }
					h3 { font-size: 24px; }
					h4 { font-size: 20px; }
					h5 { font-size: 16px; }
					h6 { font-size: 14px; }
					p {
						margin: 10px 0;
					}
					ul, ol {
						padding-left: 24px;
						margin-bottom: 16px;
					}
					ul li, ol li {
						margin-bottom: 8px;
					}
					pre {
						white-space: pre-wrap;
						word-wrap: break-word;
						overflow-wrap: break-word;
					}
					code {
						font-family: \'figtree\', sans-serif;
						font-size: 14px;
						color: #111827;
						background-color: #f3f4f6;
					}
					img.alignleft {
						float: left;
						margin: 0 15px 15px 0;
					}
					img.alignright {
						float: right;
						margin: 0 0 15px 15px;
					}
					img.aligncenter {
						display: block;
						margin-left: auto;
						margin-right: auto;
					}';
	}
}
