<?php
/**
 * Prevents WooCommerce "Duplicate" from copying eMAG identity meta.
 *
 * A duplicated product inheriting _skyemag_vendor_ext_id would claim the
 * same eMAG offer as the original: batch syncs get rejected by eMAG with
 * "Duplicate product found, please submit each product only once", and a
 * single-product sync would silently overwrite the original offer's price
 * and stock. A duplicate must start with a clean eMAG slate.
 *
 * @package SkyEmagSync
 */

namespace SkyEmagSync\Products;

use SkyEmagSync\PostMeta;

defined( 'ABSPATH' ) || exit;

class DuplicateGuard {

    public function register(): void {
        add_filter( 'woocommerce_duplicate_product_exclude_meta', [ $this, 'exclude_meta' ], 10, 2 );
    }

    /**
     * Exclude every plugin meta key from product duplication.
     *
     * @param array $exclude       Meta keys WooCommerce will skip when copying.
     * @param array $existing_keys Meta keys present on the source product
     *                             (passed by newer WooCommerce; empty on older).
     * @return array
     */
    public function exclude_meta( $exclude, $existing_keys = [] ): array {
        $exclude = (array) $exclude;

        // Primary: exclude every plugin key actually present on the source.
        foreach ( (array) $existing_keys as $key ) {
            if ( 0 === strpos( (string) $key, '_skyemag_' ) ) {
                $exclude[] = (string) $key;
            }
        }

        // Fallback for WooCommerce versions that do not pass $existing_keys:
        // the full list of known plugin keys, derived from PostMeta constants
        // so new keys are covered automatically.
        try {
            $constants = ( new \ReflectionClass( PostMeta::class ) )->getConstants();
            foreach ( $constants as $value ) {
                if ( is_string( $value ) && 0 === strpos( $value, '_skyemag_' ) ) {
                    $exclude[] = $value;
                }
            }
        } catch ( \ReflectionException $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
            // Constants unavailable — the prefix scan above still applies.
        }

        return array_values( array_unique( $exclude ) );
    }
}
