<?php
/**
 * Per-product identifier fields for WooCommerce.
 *
 * Provides GTIN8, GTIN12, GTIN13, GTIN14, MPN, and ISBN fields
 * on both the product edit page and individual variation rows,
 * allowing all identifier types to be stored simultaneously
 * per product or per variation.
 *
 * @package SEOvaultSEO\WooCommerce
 */

namespace SEOvaultSEO\WooCommerce;

use SEOvaultSEO\Core\Options;

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

class Product_Identifiers {

	/**
	 * Meta key for storing per-product identifier values.
	 */
	const META_KEY = '_seovaultseo_product_identifiers';

	/**
	 * Allowed identifier types and their labels.
	 *
	 * @var array
	 */
	protected $identifier_types = array(
		'gtin8'  => 'GTIN-8',
		'gtin12' => 'GTIN-12 (UPC)',
		'gtin13' => 'GTIN-13 (EAN)',
		'gtin14' => 'GTIN-14',
		'mpn'    => 'MPN',
		'isbn'   => 'ISBN',
	);

	/**
	 * Singleton instance.
	 *
	 * @var Product_Identifiers|null
	 */
	private static $instance = null;

	/**
	 * Get singleton.
	 *
	 * @return Product_Identifiers
	 */
	public static function get_instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Constructor — registers hooks when enabled.
	 */
	private function __construct() {
		if ( ! is_admin() ) {
			return;
		}

		add_action( 'woocommerce_product_options_sku', array( $this, 'render_product_fields' ) );
		add_action( 'woocommerce_product_after_variable_attributes', array( $this, 'render_variation_fields' ), 10, 3 );
		add_action( 'woocommerce_admin_process_product_object', array( $this, 'save_product_identifiers' ) );
		add_action( 'woocommerce_save_product_variation', array( $this, 'save_variation_identifiers' ), 10, 2 );
	}

	/**
	 * Get the list of allowed identifier types.
	 *
	 * @return array
	 */
	public function get_identifier_types() {
		return $this->identifier_types;
	}

	/**
	 * Retrieve stored identifiers for a product.
	 *
	 * @param int $product_id Product or variation ID.
	 * @return array Associative array of type => value.
	 */
	public function get_identifiers( $product_id ) {
		$product_id = absint( $product_id );

		if ( ! $product_id ) {
			return array();
		}

		$values = get_post_meta( $product_id, self::META_KEY, true );

		$clean = array();
		foreach ( $this->identifier_types as $type => $label ) {
			$clean[ $type ] = ( is_array( $values ) && isset( $values[ $type ] ) ) ? sanitize_text_field( $values[ $type ] ) : '';
		}

		return $clean;
	}

	/**
	 * Get a single identifier value for a product.
	 *
	 * @param int    $product_id Product or variation ID.
	 * @param string $type       Identifier type key.
	 * @return string
	 */
	public function get_identifier( $product_id, $type ) {
		$product_id = absint( $product_id );

		if ( ! $product_id || ! isset( $this->identifier_types[ $type ] ) ) {
			return '';
		}

		$values = $this->get_identifiers( $product_id );

		return $values[ $type ] ?? '';
	}

	/**
	 * Sanitize raw identifier data from POST input.
	 *
	 * @param array $raw Raw POST data.
	 * @return array Sanitized associative array.
	 */
	public function sanitize_identifiers( $raw ) {
		if ( ! is_array( $raw ) ) {
			return array();
		}

		$clean = array();
		foreach ( $this->identifier_types as $type => $label ) {
			$clean[ $type ] = isset( $raw[ $type ] ) ? sanitize_text_field( wp_unslash( $raw[ $type ] ) ) : '';
		}

		return $clean;
	}

	/**
	 * Save identifiers for a product.
	 *
	 * @param int   $product_id Product ID.
	 * @param array $values     Sanitized identifier values.
	 * @return bool
	 */
	public function store_identifiers( $product_id, $values ) {
		$product_id = absint( $product_id );

		if ( ! $product_id ) {
			return false;
		}

		if ( ! is_array( $values ) ) {
			return false;
		}

		$filtered = array();
		foreach ( $this->identifier_types as $type => $label ) {
			$filtered[ $type ] = isset( $values[ $type ] ) ? sanitize_text_field( $values[ $type ] ) : '';
		}

		$result = update_post_meta( $product_id, self::META_KEY, $filtered );

		return false !== $result;
	}

	/**
	 * Render identifier fields on the product edit page (Inventory tab).
	 *
	 * @return void
	 */
	public function render_product_fields() {
		$post_id = get_the_ID();

		if ( ! $post_id ) {
			return;
		}

		$values = $this->get_identifiers( $post_id );

		wp_nonce_field( 'seovaultseo_product_identifiers', '_seovaultseo_pids_nonce' );

		echo '<div class="seovaultseo-product-identifiers" style="border-top:1px solid #eee; padding-top:10px; margin-top:10px;">';
		echo '<h4>' . esc_html__( 'Product Identifiers', 'seovault-ai' ) . '</h4>';
		echo '<p class="description">' . esc_html__( 'Enter unique product identifiers for schema markup. All non-empty values are included in the structured data.', 'seovault-ai' ) . '</p>';

		foreach ( $this->identifier_types as $type => $label ) {
			$value = $values[ $type ] ?? '';
			$this->render_single_field( $type, $label, $value, 'seovaultseo_pid' );
		}

		echo '</div>';
	}

	/**
	 * Render identifier fields for a variation.
	 *
	 * @param int    $loop           Loop index.
	 * @param array  $variation_data Variation data.
	 * @param object $variation      Variation object.
	 * @return void
	 */
	public function render_variation_fields( $loop, $variation_data, $variation ) {
		if ( ! is_object( $variation ) || empty( $variation->ID ) ) {
			return;
		}

		$values = $this->get_identifiers( $variation->ID );

		echo '<div class="seovaultseo-variation-identifiers" style="border-top:1px solid #eee; padding-top:10px; margin-top:10px;">';
		echo '<h4>' . esc_html__( 'Product Identifiers', 'seovault-ai' ) . '</h4>';

		foreach ( $this->identifier_types as $type => $label ) {
			$value = $values[ $type ] ?? '';
			$this->render_single_field( $type, $label, $value, 'seovaultseo_pid_var_' . $variation->ID );
		}

		echo '</div>';
	}

	/**
	 * Render a single text input for an identifier.
	 *
	 * @param string $type  Identifier type key.
	 * @param string $label Human-readable label.
	 * @param string $value Current value.
	 * @param string $name_prefix Form field name prefix.
	 * @return void
	 */
	protected function render_single_field( $type, $label, $value, $name_prefix ) {
		$name = $name_prefix . '[' . $type . ']';
		$id   = $name_prefix . '_' . $type;

		echo '<p class="form-field">';
		echo '<label for="' . esc_attr( $id ) . '">' . esc_html( $label ) . '</label>';
		echo '<input type="text" id="' . esc_attr( $id ) . '" name="' . esc_attr( $name ) . '" value="' . esc_attr( $value ) . '" class="short" />';
		echo '</p>';
	}

	/**
	 * Save product-level identifiers from POST data.
	 *
	 * @param \WC_Product $product Product object being saved.
	 * @return void
	 */
	public function save_product_identifiers( $product ) {
		if ( ! is_object( $product ) || ! method_exists( $product, 'get_id' ) ) {
			return;
		}

		if ( ! isset( $_POST['_seovaultseo_pids_nonce'] ) ) {
			return;
		}

		$nonce = sanitize_text_field( wp_unslash( $_POST['_seovaultseo_pids_nonce'] ) );
		if ( ! wp_verify_nonce( $nonce, 'seovaultseo_product_identifiers' ) ) {
			return;
		}

		if ( ! current_user_can( 'edit_post', $product->get_id() ) ) {
			return;
		}

		if ( ! isset( $_POST['seovaultseo_pid'] ) ) {
			return;
		}

		$raw    = is_array( $_POST['seovaultseo_pid'] )
			? map_deep( wp_unslash( $_POST['seovaultseo_pid'] ), 'sanitize_text_field' )
			: array();
		$values = $this->sanitize_identifiers( $raw );

		$this->store_identifiers( $product->get_id(), $values );
	}

	/**
	 * Save variation-level identifiers from POST data.
	 *
	 * @param int $variation_id Variation ID.
	 * @param int $index        Variation index in the form.
	 * @return void
	 */
	public function save_variation_identifiers( $variation_id, $index ) {
		$variation_id = absint( $variation_id );

		if ( ! $variation_id ) {
			return;
		}

		if ( ! current_user_can( 'edit_post', $variation_id ) ) {
			return;
		}

		$nonce = isset( $_POST['woocommerce_meta_nonce'] )
			? sanitize_text_field( wp_unslash( $_POST['woocommerce_meta_nonce'] ) )
			: '';
		if ( ! wp_verify_nonce( $nonce, 'woocommerce_save_data' ) ) {
			return;
		}

		$post_key = 'seovaultseo_pid_var_' . $variation_id;

		if ( ! isset( $_POST[ $post_key ] ) ) {
			return;
		}

		$raw    = is_array( $_POST[ $post_key ] )
			? map_deep( wp_unslash( $_POST[ $post_key ] ), 'sanitize_text_field' )
			: array();
		$values = $this->sanitize_identifiers( $raw );

		$this->store_identifiers( $variation_id, $values );
	}

	/**
	 * Get schema-ready identifier properties for a product or variation.
	 *
	 * Returns an associative array of schema.org property => value
	 * for all non-empty identifiers.
	 *
	 * @param int $product_id Product or variation ID.
	 * @return array
	 */
	public function get_schema_identifiers( $product_id ) {
		$values   = $this->get_identifiers( $product_id );
		$schema   = array();
		$has_isbn = false;

		foreach ( $values as $type => $value ) {
			if ( '' !== $value ) {
				$schema[ $type ] = $value;
				if ( 'isbn' === $type ) {
					$has_isbn = true;
				}
			}
		}

		return array(
			'properties' => $schema,
			'has_isbn'   => $has_isbn,
		);
	}
}
