<?php
/**
 * File Path: includes/import/class-mbs-importer-genesis-author-pro.php
 *
 * MBS_Importer_Genesis_Author_Pro -- Competitor WXR importer for Genesis / Osom Author Pro.
 *
 * Accepts a WXR export from the Genesis Author Pro (Osom) plugin (post type: books).
 * All book data is stored in a single serialised array under the meta key
 * _genesis_author_pro; this class safely deserialises the blob (no object injection) and maps each field.
 * Part of the CI-005 competitor-importer series.
 *
 * Tier: FREE (competitor migration -- no mbs_is_pro() gate).
 *
 * @package    My_Book_Showroom
 * @subpackage Includes/Import
 * @since      1.2.0
 *
 * @see PATCHES/SPEC-COMPETITOR-IMPORTERS.md §3.5
 */

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

/**
 * MBS_Importer_Genesis_Author_Pro
 *
 * Extends MBS_Competitor_WXR_Base and implements the three abstract methods
 * required to drive the shared XMLReader streaming loop.
 *
 * source_key()      -- Returns 'genesis-author-pro'.
 * target_cpt()      -- Returns 'books' (shared CPT with WP Books Gallery).
 * matches_source()  -- Confirms Genesis by presence of '_genesis_author_pro' meta key.
 * map_item()        -- Unserialises _genesis_author_pro and maps to MBS data array.
 *
 * @since 1.2.0
 */
class MBS_Importer_Genesis_Author_Pro extends MBS_Competitor_WXR_Base { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- mbs_/MBS_ prefix is correct; scanner not configured with plugin prefix

	// ── Abstract method implementations ───────────────────────────────────────

	/**
	 * Canonical source identifier used in telemetry and AJAX routing.
	 *
	 * @since  1.2.0
	 * @return string
	 */
	protected static function source_key(): string {
		return 'genesis-author-pro';
	}

	/**
	 * WXR post_type value that identifies Genesis Author Pro items.
	 *
	 * @since  1.2.0
	 * @return string
	 */
	protected static function target_cpt(): string {
		return 'books';
	}

	/**
	 * Confirms this WXR file came from Genesis Author Pro (not WP Books Gallery,
	 * which shares the same 'books' CPT). Checks for the _genesis_author_pro key.
	 *
	 * @since  1.2.0
	 * @param  string[] $meta_keys Meta keys collected from the first item.
	 * @return bool
	 */
	protected static function matches_source( array $meta_keys ): bool {
		return in_array( '_genesis_author_pro', $meta_keys, true );
	}

	/**
	 * Map a raw WXR item array into the normalised MBS data shape.
	 *
	 * Deserialises the _genesis_author_pro value with unserialize( ..., ['allowed_classes' => false] ) and maps each
	 * key per spec §3.5. Up to three buy buttons are resolved via
	 * MBS_Importer_Retailer_Detector::detect_from_url() (URL domain takes
	 * priority over button text per spec -- labels are user-defined).
	 *
	 * @since  1.2.0
	 * @param  array $item_data  Raw item from the streaming loop:
	 *                           title, content, post_type, meta[], categories[].
	 * @return array|null  Normalised MBS data array, or null to skip.
	 */
	protected static function map_item( array $item_data ): ?array {
		$meta  = $item_data['meta'] ?? array();
		$cats  = $item_data['categories'] ?? array();
		$notes = array();

		// ── Deserialise the single meta blob ───────────────────────────────────
		$raw_blob = $meta['_genesis_author_pro'] ?? '';
		$gap      = array();
		if ( '' !== $raw_blob ) {
			$unserialized = ( is_serialized( $raw_blob ) ? unserialize( $raw_blob, array( 'allowed_classes' => false ) ) : $raw_blob );
			if ( is_array( $unserialized ) ) {
				$gap = $unserialized;
			}
		}

		// ── ISBN ───────────────────────────────────────────────────────────────
		$raw_isbn = $gap['isbn'] ?? '';
		$isbn13   = '' !== $raw_isbn
			? MBS_ISBN_Helper::normalize_isbn( $raw_isbn )
			: '';

		// ── Format slug ──────────────────────────────────────────────────────────
		// Genesis Author Pro has no dedicated format field. The free-text
		// 'available' field (e.g. "Hardback, Paperback, Kindle") is used to
		// infer the primary format slug; defaults to 'paperback' when absent.
		$gap_format_raw = sanitize_text_field( $gap['available'] ?? '' );
		$format_slug    = static::normalize_format( $gap_format_raw );

		// ── Format row ─────────────────────────────────────────────────────────
		$format_row = array(
			'format'        => $format_slug,
			'isbn13'        => $isbn13,
			'price'         => '' !== ( $gap['price'] ?? '' )
				? floatval( $gap['price'] )
				: null,
			'edition_notes' => sanitize_text_field( $gap['edition'] ?? '' ),
			'pub_date'      => sanitize_text_field( $gap['publication_date'] ?? '' ),
		);

		// ── Buy links (buttons 1-3) ────────────────────────────────────────────
		$buy_links = array();
		for ( $i = 1; $i <= 3; $i++ ) {
			$url   = esc_url_raw( $gap[ 'button_' . $i . '_uri' ] ?? '' );
			$label = sanitize_text_field( $gap[ 'button_' . $i . '_text' ] ?? '' );
			if ( '' === $url ) {
				continue;
			}
			// URL-domain detection takes priority over label (spec §3.5).
			$retailer_key = MBS_Importer_Retailer_Detector::detect_from_url( $url );
			if ( '' === $retailer_key && '' !== $label ) {
				$retailer_key = MBS_Importer_Retailer_Detector::detect_from_label( $label );
			}
			$buy_links[] = array(
				'url'          => $url,
				'retailer_key' => $retailer_key,
				'label'        => $label,
			);
		}

		// ── Postmeta ───────────────────────────────────────────────────────────
		$post_meta = array();

		$publisher = sanitize_text_field( $gap['publisher'] ?? '' );
		if ( '' !== $publisher ) {
			$post_meta['mbs_publisher'] = $publisher;
		}

		$featured_text = sanitize_text_field( $gap['featured_text'] ?? '' );
		if ( '' !== $featured_text ) {
			$post_meta['mbs_genesis_featured_text'] = $featured_text;
		}

		// 'available' is a free-form list e.g. "Hardback, Paperback, Kindle".
		$available = sanitize_text_field( $gap['available'] ?? '' );
		if ( '' !== $available ) {
			$post_meta['mbs_genesis_formats_available'] = $available;
		}

		// ── Taxonomies ─────────────────────────────────────────────────────────
		$taxonomies = array();

		foreach ( $cats as $cat ) {
			$domain = $cat['domain'] ?? '';
			$name   = sanitize_text_field( $cat['name'] ?? '' );
			if ( '' === $name ) {
				continue;
			}
			switch ( $domain ) {
				case 'book':       // Genesis author taxonomy slug is 'book'
					$taxonomies[ MBS_TAX_AUTHOR ][] = $name;
					break;
				case 'book_series':
					$taxonomies[ MBS_TAX_SERIES ][] = $name;
					break;
				case 'book_tag':
					$taxonomies[ MBS_TAX_TAG ][] = $name;
					break;
				default:
					break;
			}
		}

		// 'editor' field → MBS_TAX_CONTRIBUTOR term (spec §3.5).
		$editor = sanitize_text_field( $gap['editor'] ?? '' );
		if ( '' !== $editor ) {
			$taxonomies[ MBS_TAX_CONTRIBUTOR ][] = $editor;
		}

		return array(
			'title'      => sanitize_text_field( $item_data['title'] ?? '' ),
			'content'    => wp_kses_post( $item_data['content'] ?? '' ),
			'post_meta'  => $post_meta,
			'format_row' => $format_row,
			'buy_links'  => $buy_links,
			'taxonomies' => $taxonomies,
			'notes'      => $notes,
		);
	}
}
