<?php
/**
 * File Path: includes/import/class-mbs-importer-amazon.php
 *
 * Amazon Importer (PRO)
 *
 * Fetches book metadata from the Amazon Product Advertising API (PA-API v5)
 * using credentials stored encrypted in wp_options (GP-SEC-1). Credentials
 * are never transmitted to any DMRS Tech server — they live exclusively in
 * the site's own WordPress database (see upgrade page privacy notice).
 *
 * Architecture: same two-step fetch → confirm → insert pattern as Google Books
 * and Open Library importers.
 *   fetch()  — fetches metadata from PA-API, returns candidates. No insertion.
 *   Tab 5 JS presents candidates; admin confirms selection.
 *   Tab 5 AJAX handler calls MBS_Importer_CSV::import_candidates().
 *
 * Note: MBS_Amazon_PAAPI is the PA-API v5 HTTP client class. Its implementation
 * is out of scope here — it must return an array with at minimum a 'title' key,
 * and any of the optional keys listed in MBS_Importer_CSV::ACCEPTED_COLUMNS.
 *
 * @package MyBookShowroom
 * @since   1.0.0
 */

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

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

	/**
	 * Fetch book metadata from Amazon PA-API for a list of ASIN or ISBN codes.
	 *
	 * Returns a candidate list for Tab 5 confirmation UI.
	 * Does NOT insert anything — insertion is the admin's next step.
	 *
	 * @param string[] $codes ASIN or ISBN-13 values.
	 * @return array{
	 *   success: bool,
	 *   candidates: array[],
	 *   not_found: string[],
	 *   errors: string[],
	 *   error: string
	 * }
	 */
	public static function fetch( array $codes ): array {
		$result = array(
			'success'    => false,
			'candidates' => array(),
			'not_found'  => array(),
			'errors'     => array(),
			'error'      => '',
		);

		if ( ! mbs_is_registered() || ! mbs_is_pro() ) {
			$result['error'] = 'Amazon import requires a registered PRO license.';
			return $result;
		}

		// Decrypt PA-API credentials (GP-SEC-1).
		$access_key = mbs_decrypt_option( 'mbs_setting_import_amazon_api_key_encrypted' );
		$secret_key = mbs_decrypt_option( 'mbs_setting_import_amazon_api_secret_encrypted' );
		$partner    = get_option( 'mbs_setting_amazon_partner_tag', '' );

		if ( empty( $access_key ) || empty( $secret_key ) || empty( $partner ) ) {
			$result['error'] = 'Amazon PA-API credentials are not configured. Go to Settings → Import/Export to add them.';
			return $result;
		}

		$codes = array_filter( array_map( 'trim', $codes ) );

		if ( empty( $codes ) ) {
			$result['error'] = 'No ASIN or ISBN codes provided.';
			return $result;
		}

		foreach ( $codes as $code ) {
			$raw_data = MBS_Amazon_PAAPI::lookup( $code, $access_key, $secret_key, $partner );

			if ( ! $raw_data || is_wp_error( $raw_data ) ) {
				$message = is_wp_error( $raw_data ) ? $raw_data->get_error_message() : 'Lookup returned no data.';
				$result['errors'][] = $code . ': ' . $message;
				continue;
			}

			$candidate = self::normalise_candidate( $raw_data, $code );
			if ( null !== $candidate ) {
				$result['candidates'][] = $candidate;
			} else {
				$result['not_found'][] = $code;
			}
		}

		$result['success'] = true;
		return $result;
	}

	/**
	 * Fetch candidates and immediately insert confirmed ones.
	 *
	 * Convenience method for when the admin has already confirmed the import
	 * (i.e., no confirmation UI step). Delegates to import_candidates() for
	 * the canonical duplicate detection + insert path.
	 *
	 * M-2: Uses MBS_Duplicate_Detector::check() via import_candidates().
	 * NEW-C2: No phantom MBS_Book_Meta_Helper call — insert_book() handles all meta.
	 *
	 * @param string[] $codes            ASIN or ISBN-13 values.
	 * @param array    $force_insert_keys Keys approved for force-insert.
	 * @return array Same shape as MBS_Importer_CSV::import_candidates().
	 */
	public static function import(
		array $codes,
		array $force_insert_keys = array()
	): array {
		$fetch = self::fetch( $codes );

		if ( ! $fetch['success'] ) {
			return array(
				'success'    => false,
				'inserted'   => 0,
				'skipped'    => 0,
				'duplicates' => array(),
				'errors'     => $fetch['errors'],
				'error'      => $fetch['error'],
			);
		}

		if ( empty( $fetch['candidates'] ) ) {
			return array(
				'success'    => true,
				'inserted'   => 0,
				'skipped'    => 0,
				'duplicates' => array(),
				'errors'     => $fetch['errors'],
				'error'      => '',
			);
		}

		// NEW-C2: All insertion goes through the canonical path.
		// M-2:    import_candidates() uses check() not find_duplicate().
		return MBS_Importer_CSV::import_candidates( $fetch['candidates'], $force_insert_keys );
	}

	// =========================================================================
	// Private helpers
	// =========================================================================

	/**
	 * Normalise a raw PA-API response array to the canonical MBS candidate shape.
	 *
	 * @param array  $raw_data PA-API lookup result from MBS_Amazon_PAAPI::lookup().
	 * @param string $code     The ASIN or ISBN used in the lookup (for _line).
	 * @return array|null Candidate, or null if title is absent.
	 */
	private static function normalise_candidate( array $raw_data, string $code ): ?array {
		$title = trim( $raw_data['title'] ?? '' );
		if ( empty( $title ) ) {
			return null;
		}

		$isbn13 = '';
		if ( ! empty( $raw_data['isbn13'] ) ) {
			$isbn13 = MBS_ISBN_Helper::normalize_isbn( $raw_data['isbn13'] ) ?: '';
		}

		return array(
			'_source'      => 'amazon',
			'_line'        => $code,  // used in error messages
			'title'        => $title,
			'author'       => trim( $raw_data['author'] ?? $raw_data['primary_author'] ?? '' ),
			'isbn13'       => $isbn13,
			'asin'         => trim( $raw_data['asin'] ?? $code ),
			'publisher'    => trim( $raw_data['publisher'] ?? '' ),
			'pub_date'     => trim( $raw_data['pub_date'] ?? $raw_data['publication_date'] ?? '' ),
			'format'       => trim( $raw_data['format'] ?? 'paperback' ),
			'price'        => (string) ( $raw_data['price'] ?? '' ),
			'page_length'  => (string) ( $raw_data['page_length'] ?? '' ),
			'post_content' => sanitize_textarea_field( $raw_data['description'] ?? $raw_data['post_content'] ?? '' ),
			'cover_url'    => esc_url_raw( $raw_data['cover_url'] ?? $raw_data['large_image_url'] ?? '' ),
		);
	}
}
