<?php
/**
 * File Path: includes/api/class-mbs-onix-parser.php
 *
 * ONIX XML Parser Dispatcher -- My Book Showroom
 *
 * Accepts a raw ONIX XML string (2.1, 3.0, or 3.1; short or reference tags).
 * Detects the version from the root element's release attribute and
 * delegates to the appropriate version-specific parser.
 *
 * @package    My_Book_Showroom
 * @subpackage Includes/Api
 * @since      1.1.0
 */

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

class MBS_Onix_Parser { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- mbs_/MBS_ prefix is correct; scanner not configured with plugin prefix

	/**
	 * Parse an ONIX XML string into normalised product arrays.
	 *
	 * Supports ONIX 2.1 and 3.0. Version is auto-detected from the
	 * root element's release attribute. If the attribute is absent or
	 * equals '2.1' the 2.1 parser is used; '3.0' routes to the 3.0 parser.
	 *
	 * @param string $xml_string Raw XML content.
	 * @param array  &$stats     Import stats array; errors are appended on failure.
	 * @return array[] Array of normalised product arrays (empty on parse failure).
	 */
	public function parse( string $xml_string, array &$stats ): array {
		// Disable external entity loading (XXE defense).
		$prev = libxml_use_internal_errors( true );
		$xml  = simplexml_load_string( $xml_string, 'SimpleXMLElement', LIBXML_NONET | LIBXML_NOENT | LIBXML_NOERROR );
		libxml_use_internal_errors( $prev );

		if ( false === $xml ) {
			$stats['errors'][] = __( 'Could not parse the XML file. Please ensure it is valid ONIX XML.', 'my-book-showroom' );
			return array();
		}

		// Detect ONIX version from root element release attribute.
		$release = (string) ( $xml->attributes()->release ?? '' );

		if ( '3.1' === $release ) {
			$products = ( new MBS_Onix_Parser_31() )->parse_products( $xml, $stats );
		} elseif ( '3.0' === $release ) {
			$products = ( new MBS_Onix_Parser_30() )->parse_products( $xml, $stats );
		} else {
			// Absent release attribute or explicit '2.1' both route to the 2.1 parser.
			$products = ( new MBS_Onix_Parser_21() )->parse_products( $xml, $stats );
		}

		if ( empty( $products ) && empty( $stats['errors'] ) ) {
			$stats['errors'][] = __( 'No valid product records found in the ONIX file.', 'my-book-showroom' );
		}

		return $products;
	}
}
