<?php
/**
 * File Path: includes/import/class-mbs-import-taxonomy-restorer.php
 *
 * MBS Import Taxonomy Restorer
 *
 * Restores MBS taxonomy terms from a parsed taxonomy.json data array
 * (produced by MBS_Exporter_Zip). Extracted from MBS_Import_Orchestrator
 * per the SRP rule in Sprint Plan §Phase 6 (IEF-A-012).
 *
 * Restoration strategy:
 *   - For each taxonomy in the import data, iterate the term list.
 *   - If a term with the same name already exists in the taxonomy, skip it
 *     (the hydrator will associate the book with the existing term by name).
 *   - If the term does not exist, create it via wp_insert_term() with the
 *     description and parent from the export data.
 *   - Term meta (non-private keys) is written via update_term_meta() after
 *     the term is confirmed to exist.
 *
 * Note: slug and term_id from the export are NOT enforced on the destination
 * site — WordPress assigns new IDs/slugs. The canonical import key for term
 * matching is the term name (same key used by wp_set_object_terms() in
 * MBS_Book_Hydrator).
 *
 * @package    My_Book_Showroom
 * @since      1.0.0
 */

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

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

	/**
	 * Restore taxonomy terms from taxonomy.json data.
	 *
	 * @param array $taxonomy_data Parsed taxonomy.json (keyed by taxonomy slug).
	 * @return array{created: int, skipped: int, errors: string[]} Result summary.
	 */
	public static function restore( array $taxonomy_data ): array {
		$result = array(
			'created' => 0,
			'skipped' => 0,
			'errors'  => array(),
		);

		$supported = array(
			'mbs_author', 'mbs_genre', 'mbs_series', 'mbs_tag',
			'mbs_publisher', 'mbs_imprint', 'mbs_universe',
			'mbs_collection', 'mbs_contributor',
			'mbs_theme', 'mbs_content_warning',
		);

		foreach ( $supported as $tax ) {
			if ( empty( $taxonomy_data[ $tax ] ) || ! is_array( $taxonomy_data[ $tax ] ) ) {
				continue;
			}

			foreach ( $taxonomy_data[ $tax ] as $term_row ) {
				if ( empty( $term_row['name'] ) ) {
					continue;
				}

				$name        = sanitize_text_field( $term_row['name'] );
				$description = sanitize_textarea_field( $term_row['description'] ?? '' );
				$parent      = (int) ( $term_row['parent'] ?? 0 );
				$term_meta   = is_array( $term_row['term_meta'] ?? null ) ? $term_row['term_meta'] : array();

				// Check whether the term already exists by name.
				$existing = term_exists( $name, $tax );

				if ( $existing ) {
					$term_id = (int) ( $existing['term_id'] ?? 0 );
					$result['skipped']++;
				} else {
					$insert_args = array( 'description' => $description );
					if ( $parent > 0 ) {
						// Only set parent if a term with that name exists; IDs differ across sites.
						$insert_args['parent'] = 0; // Flat import; parent re-linking not in scope.
					}

					$inserted = wp_insert_term( $name, $tax, $insert_args );
					if ( is_wp_error( $inserted ) ) {
						$result['errors'][] = sprintf(
							'Could not create term "%s" in %s: %s',
							esc_html( $name ),
							esc_html( $tax ),
							$inserted->get_error_message()
						);
						continue;
					}
					$term_id = (int) $inserted['term_id'];
					$result['created']++;
				}

				// Write non-private term meta.
				foreach ( $term_meta as $meta_key => $meta_value ) {
					$meta_key = sanitize_key( (string) $meta_key );
					if ( '' === $meta_key || str_starts_with( $meta_key, '_' ) ) {
						continue;
					}
					update_term_meta( $term_id, $meta_key, $meta_value );
				}
			}
		}

		return $result;
	}
}
