<?php
/**
 * WooCommerce CSV Import/Export integration for product identifiers.
 *
 * Adds GTIN8, GTIN12, GTIN13, GTIN14, ISBN, and MPN columns to the
 * WooCommerce Product CSV Export, provides automatic column mapping
 * for CSV Import, and processes imported values into the plugin's
 * per-product identifier meta.
 *
 * @package SEOvaultSEO\WooCommerce
 */

namespace SEOvaultSEO\WooCommerce;

use SEOvaultSEO\Core\Options;

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

class Import_Export {

	/**
	 * Allowed identifier types and their export column labels.
	 *
	 * @var array
	 */
	protected $identifier_columns = array(
		'gtin8'  => 'GTIN8',
		'gtin12' => 'GTIN12 / UPC',
		'gtin13' => 'GTIN13 / EAN',
		'gtin14' => 'GTIN14 / ITF-14',
		'isbn'   => 'ISBN',
		'mpn'    => 'MPN',
	);

	/**
	 * Automatic column mapping: CSV header => internal identifier key.
	 *
	 * @var array
	 */
	protected $auto_mapping = array(
		'GTIN8'           => 'gtin8',
		'gtin8'           => 'gtin8',
		'GTIN12 / UPC'    => 'gtin12',
		'GTIN12/UPC'      => 'gtin12',
		'gtin12 / upc'    => 'gtin12',
		'gtin12/upc'      => 'gtin12',
		'GTIN12'          => 'gtin12',
		'gtin12'          => 'gtin12',
		'UPC'             => 'gtin12',
		'upc'             => 'gtin12',
		'GTIN13 / EAN'    => 'gtin13',
		'GTIN13/EAN'      => 'gtin13',
		'gtin13 / ean'    => 'gtin13',
		'gtin13/ean'      => 'gtin13',
		'GTIN13'          => 'gtin13',
		'gtin13'          => 'gtin13',
		'EAN'             => 'gtin13',
		'ean'             => 'gtin13',
		'GTIN14 / ITF-14' => 'gtin14',
		'GTIN14/ITF-14'   => 'gtin14',
		'gtin14 / itf-14' => 'gtin14',
		'gtin14/itf-14'   => 'gtin14',
		'GTIN14'          => 'gtin14',
		'gtin14'          => 'gtin14',
		'ITF-14'          => 'gtin14',
		'itf-14'          => 'gtin14',
		'ISBN'            => 'isbn',
		'isbn'            => 'isbn',
		'MPN'             => 'mpn',
		'mpn'             => 'mpn',
	);

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

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

	/**
	 * Constructor — registers WooCommerce import/export hooks.
	 */
	private function __construct() {
		// Export: add columns.
		add_filter( 'woocommerce_product_export_column_names', array( $this, 'add_export_columns' ) );
		add_filter( 'woocommerce_product_export_product_default_columns', array( $this, 'add_export_columns' ) );

		// Export: provide data for each identifier column.
		foreach ( array_keys( $this->identifier_columns ) as $type ) {
			add_filter( 'woocommerce_product_export_product_column_' . $type, array( $this, 'export_identifier_value' ), 10, 2 );
		}

		// Import: add columns to mapping options.
		add_filter( 'woocommerce_csv_product_import_mapping_options', array( $this, 'add_export_columns' ) );

		// Import: automatic column mapping for common header names.
		add_filter( 'woocommerce_csv_product_import_mapping_default_columns', array( $this, 'add_auto_mapping' ) );

		// Import: process imported data before product is saved.
		add_filter( 'woocommerce_product_import_pre_insert_product_object', array( $this, 'process_import' ), 10, 2 );
	}

	// =========================================================================
	// Export
	// =========================================================================

	/**
	 * Add identifier columns to the WooCommerce export column list.
	 *
	 * @param array $columns Existing column definitions.
	 * @return array
	 */
	public function add_export_columns( $columns ) {
		if ( ! is_array( $columns ) ) {
			$columns = array();
		}

		foreach ( $this->identifier_columns as $key => $label ) {
			if ( ! isset( $columns[ $key ] ) ) {
				$columns[ $key ] = $label;
			}
		}

		return $columns;
	}

	/**
	 * Provide the export value for a single identifier column.
	 *
	 * @param mixed       $value   Default value (empty string).
	 * @param \WC_Product $product Product object being exported.
	 * @return string
	 */
	public function export_identifier_value( $value, $product ) {
		$current_hook = current_filter();
		$prefix       = 'woocommerce_product_export_product_column_';

		if ( strpos( $current_hook, $prefix ) !== 0 ) {
			return $value;
		}

		$identifier_type = str_replace( $prefix, '', $current_hook );

		if ( ! isset( $this->identifier_columns[ $identifier_type ] ) ) {
			return $value;
		}

		if ( ! is_object( $product ) || ! method_exists( $product, 'get_id' ) ) {
			return '';
		}

		$product_id = $product->get_id();

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

		// Check per-product identifiers first.
		$pid = Product_Identifiers::get_instance();
		$val = $pid->get_identifier( $product_id, $identifier_type );

		if ( '' !== $val ) {
			return $val;
		}

		// Fall back to the single GTIN meta key if the type matches the configured type.
		if ( Options::get_wc_gtin_type() === $identifier_type ) {
			$single = get_post_meta( $product_id, WooCommerce::GTIN_META_KEY, true );
			if ( ! empty( $single ) ) {
				return (string) $single;
			}

			// Fall back to WC native global_unique_id.
			if ( method_exists( $product, 'get_global_unique_id' ) ) {
				$native = $product->get_global_unique_id();
				if ( ! empty( $native ) ) {
					return (string) $native;
				}
			}
		}

		return '';
	}

	// =========================================================================
	// Import
	// =========================================================================

	/**
	 * Add automatic column mapping for common CSV header names.
	 *
	 * @param array $columns Existing mapping: header_name => column_key.
	 * @return array
	 */
	public function add_auto_mapping( $columns ) {
		if ( ! is_array( $columns ) ) {
			$columns = array();
		}

		foreach ( $this->auto_mapping as $header => $key ) {
			if ( ! isset( $columns[ $header ] ) ) {
				$columns[ $header ] = $key;
			}
		}

		return $columns;
	}

	/**
	 * Process imported CSV data and save identifier values to product meta.
	 *
	 * @param \WC_Product $product Product object being imported or updated.
	 * @param array       $data    CSV row data keyed by column name.
	 * @return \WC_Product
	 */
	public function process_import( $product, $data ) {
		if ( ! is_object( $product ) || ! method_exists( $product, 'get_id' ) ) {
			return $product;
		}

		if ( ! is_array( $data ) ) {
			return $product;
		}

		$product_id = $product->get_id();

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

		// Collect any identifier values present in the CSV row.
		$imported = array();
		foreach ( array_keys( $this->identifier_columns ) as $type ) {
			if ( isset( $data[ $type ] ) && '' !== $data[ $type ] ) {
				$imported[ $type ] = sanitize_text_field( $data[ $type ] );
			}
		}

		if ( empty( $imported ) ) {
			return $product;
		}

		// If per-product identifiers are enabled, merge with existing values.
		if ( Options::is_wc_per_product_identifiers() ) {
			$pid      = Product_Identifiers::get_instance();
			$existing = $pid->get_identifiers( $product_id );
			$merged   = array_merge( $existing, $imported );
			$pid->store_identifiers( $product_id, $merged );
		} else {
			// Single-type mode: store only the configured type in the GTIN meta key.
			$configured_type = Options::get_wc_gtin_type();
			if ( isset( $imported[ $configured_type ] ) ) {
				update_post_meta( $product_id, WooCommerce::GTIN_META_KEY, $imported[ $configured_type ] );
			}
		}

		return $product;
	}

	// =========================================================================
	// Helpers (exposed for testing)
	// =========================================================================

	/**
	 * Get the identifier columns definition.
	 *
	 * @return array
	 */
	public function get_identifier_columns() {
		return $this->identifier_columns;
	}

	/**
	 * Get the automatic column mapping definition.
	 *
	 * @return array
	 */
	public function get_auto_mapping() {
		return $this->auto_mapping;
	}

	/**
	 * Sanitize a single identifier value.
	 *
	 * @param mixed $value Raw value.
	 * @return string
	 */
	public function sanitize_identifier( $value ) {
		if ( null === $value ) {
			return '';
		}
		return sanitize_text_field( $value );
	}

	/**
	 * Sanitize an array of identifier values.
	 *
	 * @param array $values Raw values keyed by identifier type.
	 * @return array
	 */
	public function sanitize_identifiers( $values ) {
		if ( ! is_array( $values ) ) {
			return array();
		}

		$clean = array();
		foreach ( array_keys( $this->identifier_columns ) as $type ) {
			$clean[ $type ] = isset( $values[ $type ] ) ? sanitize_text_field( $values[ $type ] ) : '';
		}

		return $clean;
	}
}
