<?php
/**
 * Safe partner product clone and replacement workflow.
 *
 * @package Niwa_AI
 */

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

if ( ! class_exists( 'Niwa_AI_Admin_Partner_Product_Image_Context' ) ) {
	require_once __DIR__ . '/class-admin-partner-product-image-context.php';
}
if ( ! class_exists( 'Niwa_AI_Admin_Partner_Product_Label_Normalizer' ) ) {
	require_once __DIR__ . '/class-admin-partner-product-label-normalizer.php';
}
if ( ! class_exists( 'Niwa_AI_Admin_Partner_Product_Variant_Media' ) ) {
	require_once __DIR__ . '/class-admin-partner-product-variant-media.php';
}

class Niwa_AI_Admin_Partner_Product_Cloner {
	private $extractor;
	private $image_context;
	private $label_normalizer;
	private $variant_media;

	public function __construct( $extractor = null, $variant_media = null, $image_context = null, $label_normalizer = null ) {
		$this->image_context = $image_context instanceof Niwa_AI_Admin_Partner_Product_Image_Context ? $image_context : new Niwa_AI_Admin_Partner_Product_Image_Context();
		$this->label_normalizer = $label_normalizer instanceof Niwa_AI_Admin_Partner_Product_Label_Normalizer ? $label_normalizer : new Niwa_AI_Admin_Partner_Product_Label_Normalizer();
		$this->variant_media = $variant_media instanceof Niwa_AI_Admin_Partner_Product_Variant_Media ? $variant_media : new Niwa_AI_Admin_Partner_Product_Variant_Media( $this->image_context );
		$this->extractor = $extractor instanceof Niwa_AI_Admin_Partner_Product_Extractor
			? $extractor
			: new Niwa_AI_Admin_Partner_Product_Extractor();
	}

	public function clone_from_url( $args ) {
		if ( ! function_exists( 'wc_get_product' ) ) {
			return array( 'success' => false, 'error' => 'WooCommerce nije dostupan.' );
		}

		$args       = is_array( $args ) ? $args : array();
		$source_url = isset( $args['source_url'] ) ? esc_url_raw( trim( (string) $args['source_url'] ) ) : '';
		$mode       = isset( $args['mode'] ) ? sanitize_key( (string) $args['mode'] ) : 'replace_existing';
		$mode       = in_array( $mode, array( 'replace_existing', 'create_new', 'update_existing' ), true ) ? $mode : 'replace_existing';

		if ( '' === $source_url ) {
			return array( 'success' => false, 'error' => 'source_url je obavezan.' );
		}

		$source = $this->extractor->extract_from_url( $source_url, array( 'max_images' => 60 ) );
		if ( empty( $source['success'] ) ) {
			return $source;
		}

		$product_data = isset( $source['product'] ) && is_array( $source['product'] ) ? $source['product'] : array();
		$product_data = $this->apply_manifest_args_to_product_data( $product_data, $args );
		$product_data = $this->variant_media->normalize_product_data( $product_data );
		$source['product'] = $product_data;
		$title        = isset( $product_data['title'] ) ? trim( (string) $product_data['title'] ) : '';
		$sku          = isset( $product_data['sku_hint'] ) ? trim( (string) $product_data['sku_hint'] ) : '';
		if ( 'create_new' === $mode && ! empty( $args['target_sku'] ) ) {
			$sku = sanitize_text_field( trim( (string) $args['target_sku'] ) );
		}
		if ( '' === $title ) {
			return array( 'success' => false, 'error' => 'Source proizvod nema pouzdan title.' );
		}

		$target_id = $this->resolve_target_product_id( $args, $sku );
		$target   = $target_id > 0 ? wc_get_product( $target_id ) : false;
		if ( 'create_new' !== $mode && ! $target ) {
			return array( 'success' => false, 'error' => 'Nisam nasao target proizvod za replace/update.' );
		}

		$preserve_categories = ! array_key_exists( 'preserve_local_categories', $args ) || ! empty( $args['preserve_local_categories'] );
		$category_ids        = $preserve_categories && $target ? array_map( 'intval', (array) $target->get_category_ids() ) : array();
		$publish_after       = ! array_key_exists( 'publish_after_verification', $args ) || ! empty( $args['publish_after_verification'] );

		if ( 'update_existing' === $mode ) {
			$product_id = intval( $target_id );
			$product    = wc_get_product( $product_id );
			if ( ! $product || ! $product->is_type( 'variable' ) ) {
				return array( 'success' => false, 'error' => 'Target za update_existing mora biti variable proizvod.' );
			}
		} else {
			$product_id = $this->create_staged_variable_product( $title, $product_data, $category_ids, $sku );
			$product    = wc_get_product( $product_id );
			if ( ! $product ) {
				return array( 'success' => false, 'error' => 'Staged proizvod nije mogao da se ucita posle kreiranja.' );
			}
		}

		$media = $this->import_source_media( $product_id, $product_data );
		if ( empty( $media['success'] ) ) {
			return $media + array( 'product_id' => $product_id );
		}

		$attributes_result = $this->sync_source_attributes( $product_id, $product_data );
		if ( empty( $attributes_result['success'] ) ) {
			return $attributes_result + array( 'product_id' => $product_id );
		}

		$variation_result = $this->recreate_source_variations( $product_id, $product_data, $media['by_url'], $mode );
		if ( empty( $variation_result['success'] ) ) {
			return $variation_result + array( 'product_id' => $product_id );
		}

		$matrix_result = $this->finalize_clone_parent_matrix( $product_id, $product_data );
		if ( empty( $matrix_result['success'] ) ) {
			return $matrix_result + array( 'product_id' => $product_id );
		}
		$verification = $this->verify_clone( $product_id, $source, $category_ids );
		if ( empty( $verification['success'] ) ) {
			return array(
				'success'      => false,
				'error'        => 'Clone verification nije prosao.',
				'product_id'   => $product_id,
				'verification' => $verification,
			);
		}

		$archived_id = 0;
		if ( 'replace_existing' === $mode && $target && intval( $target_id ) !== intval( $product_id ) ) {
			$archived = $this->archive_replaced_product( intval( $target_id ), $sku );
			if ( empty( $archived['success'] ) ) {
				return $archived + array( 'product_id' => $product_id, 'verification' => $verification );
			}
			$archived_id = intval( $target_id );
			$product     = wc_get_product( $product_id );
		}

		if ( $product && '' !== $sku ) {
			try {
				$product->set_sku( $sku );
			} catch ( Exception $e ) {
				return array( 'success' => false, 'error' => 'Final SKU greska: ' . $e->getMessage(), 'product_id' => $product_id );
			}
		}
		if ( $product && $publish_after ) {
			$product->set_status( 'publish' );
		}
		if ( $product ) {
			$product->save();
		}

		$this->apply_variation_skus_after_archive( $product_id, $product_data );
		$matrix_result = $this->finalize_clone_parent_matrix( $product_id, $product_data );
		if ( empty( $matrix_result['success'] ) ) {
			return $matrix_result + array( 'product_id' => $product_id, 'verification' => $verification );
		}
		$final_verification = $this->verify_clone( $product_id, $source, $category_ids );
		$verified           = ! empty( $final_verification['success'] );
		$final_reply        = $verified ? $this->build_final_reply( $product_id, $archived_id, $mode, $media, $variation_result, $final_verification ) : '';

		return array(
			'success'            => $verified,
			'summary'            => 'Partner proizvod je kloniran u Woo proizvod #' . $product_id . '.',
			'product_id'         => $product_id,
			'archived_product_id'=> $archived_id,
			'mode'               => $mode,
			'imported_images'    => count( $media['attachment_ids'] ),
			'variation_count'    => count( $variation_result['variation_ids'] ),
			'verification'       => $final_verification,
			'terminal_after_tool'=> $verified,
			'terminal_reason'    => $verified ? 'partner_product_clone_completed' : '',
			'final_reply'        => $final_reply,
			'postconditions'     => array(
				array(
					'id'     => 'partner_product_clone_executed',
					'status' => $verified ? 'satisfied' : 'failed',
				),
				array(
					'id'     => 'partner_product_clone_verified',
					'status' => $verified ? 'satisfied' : 'failed',
				),
			),
			'executed_actions'   => array(
				array(
					'type'                => 'clone_partner_variable_product_from_url',
					'product_id'          => $product_id,
					'archived_product_id' => $archived_id,
				),
			),
		);
	}

	private function build_final_reply( $product_id, $archived_id, $mode, $media, $variation_result, $verification ) {
		$product = wc_get_product( intval( $product_id ) );
		$title   = $product ? $product->get_name() : 'proizvod #' . intval( $product_id );
		$parts   = array(
			'Gotovo. Kloniran je "' . $title . '" u Woo proizvod #' . intval( $product_id ) . '.',
			'Importovano slika: ' . count( isset( $media['attachment_ids'] ) ? (array) $media['attachment_ids'] : array() ) . '.',
			'Kreirano varijacija: ' . count( isset( $variation_result['variation_ids'] ) ? (array) $variation_result['variation_ids'] : array() ) . '.',
		);
		if ( ! empty( $verification['variation_gallery'] ) ) {
			$with_gallery = 0;
			foreach ( (array) $verification['variation_gallery'] as $row ) {
				if ( ! empty( $row['actual_count'] ) && intval( $row['actual_count'] ) > 1 ) {
					$with_gallery++;
				}
			}
			if ( $with_gallery > 0 ) {
				$parts[] = 'Mapirane varijacione galerije: ' . intval( $with_gallery ) . '.';
			}
		}

		if ( $product ) {
			$parts[] = 'Lokalne kategorije su ostale na proizvodu.';
			$link = get_permalink( intval( $product_id ) );
			if ( is_string( $link ) && '' !== $link ) {
				$parts[] = 'URL: ' . $link;
			}
		}

		if ( intval( $archived_id ) > 0 ) {
			$parts[] = 'Stari proizvod #' . intval( $archived_id ) . ' je arhiviran posle uspesne verifikacije.';
		} elseif ( 'update_existing' === $mode ) {
			$parts[] = 'Postojeci proizvod je azuriran direktno.';
		}

		if ( ! empty( $verification['success'] ) ) {
			$parts[] = 'Verifikacija je prosla: slike, varijacije i kategorije su proverene.';
		}

		return implode( ' ', $parts );
	}

	private function resolve_target_product_id( $args, $source_sku ) {
		$product_id = isset( $args['target_product_id'] ) ? intval( $args['target_product_id'] ) : 0;
		if ( $product_id > 0 ) {
			return $product_id;
		}
		$sku = isset( $args['target_sku'] ) && '' !== trim( (string) $args['target_sku'] ) ? trim( (string) $args['target_sku'] ) : trim( (string) $source_sku );
		if ( '' !== $sku && function_exists( 'wc_get_product_id_by_sku' ) ) {
			return intval( wc_get_product_id_by_sku( $sku ) );
		}
		return 0;
	}

	private function create_staged_variable_product( $title, $product_data, $category_ids, $final_sku ) {
		$product = new WC_Product_Variable();
		$product->set_name( sanitize_text_field( $title ) );
		if ( ! empty( $product_data['description_raw'] ) ) {
			$product->set_description( wp_kses_post( (string) $product_data['description_raw'] ) );
		}
		if ( ! empty( $product_data['short_description_raw'] ) ) {
			$product->set_short_description( wp_kses_post( (string) $product_data['short_description_raw'] ) );
		}
		$product->set_status( 'draft' );
		$product->set_sku( 'niwa-staged-' . sanitize_title( $final_sku ? $final_sku : $title ) . '-' . time() );
		if ( ! empty( $category_ids ) ) {
			$product->set_category_ids( array_values( array_unique( array_map( 'intval', $category_ids ) ) ) );
		}
		return intval( $product->save() );
	}

	private function import_source_media( $product_id, $product_data ) {
		$images = $this->variant_media->collect_all_images( $product_data );
		$by_url = array();
		$ids    = array();
		foreach ( $images as $image ) {
			$url = isset( $image['url'] ) ? esc_url_raw( (string) $image['url'] ) : '';
			if ( '' === $url ) {
				continue;
			}
			$existing = $this->find_attachment_by_source_url( $url );
			if ( $existing > 0 ) {
				$attachment_id = $existing;
			} else {
				$title    = isset( $image['alt_text_suggested'] ) ? (string) $image['alt_text_suggested'] : get_the_title( $product_id );
				$ingested = Niwa_AI_Admin_Autonomy_Image_Utils::ingest_from_url( $url, $title, $product_id );
				if ( empty( $ingested['attachment_id'] ) ) {
					return array( 'success' => false, 'error' => 'Import slike nije uspeo: ' . $url );
				}
				$attachment_id = intval( $ingested['attachment_id'] );
				update_post_meta( $attachment_id, '_niwa_source_image_url', $url );
				update_post_meta( $attachment_id, '_niwa_source_image_hash', sha1( $url ) );
			}
			$ids[] = $attachment_id;
			$by_url[ $this->canonical_image_key( $url ) ] = $attachment_id;
		}
		$ids = array_values( array_unique( array_filter( array_map( 'intval', $ids ) ) ) );
		if ( empty( $ids ) ) {
			return array( 'success' => false, 'error' => 'Nijedna source slika nije importovana.' );
		}
		update_post_meta( $product_id, '_thumbnail_id', $ids[0] );
		$product = wc_get_product( $product_id );
		if ( $product ) {
			$product->set_gallery_image_ids( array_slice( $ids, 1 ) );
			$product->save();
		}
		return array(
			'success'        => true,
			'attachment_ids' => $ids,
			'by_url'         => $by_url,
		);
	}

	private function sync_source_attributes( $product_id, $product_data ) {
		$product = wc_get_product( $product_id );
		if ( ! $product || ! $product->is_type( 'variable' ) ) {
			return array( 'success' => false, 'error' => 'Ciljni proizvod nije variable.' );
		}

		$attribute_specs = $this->build_attribute_specs( $product_data );
		$term_labels     = $this->label_normalizer->term_label_map_from_product_data( $product_data );
		if ( empty( $attribute_specs ) ) {
			return array( 'success' => false, 'error' => 'Source nema atribute za variable proizvod.' );
		}

		$wc_attributes = array();
		$position      = 0;
		foreach ( $attribute_specs as $taxonomy => $spec ) {
			$label = isset( $spec['label'] ) ? (string) $spec['label'] : $taxonomy;
			$this->ensure_attribute_taxonomy( $taxonomy, $label );
			$term_ids = $this->ensure_terms( $taxonomy, isset( $spec['values'] ) ? (array) $spec['values'] : array(), isset( $term_labels[ $taxonomy ] ) ? (array) $term_labels[ $taxonomy ] : array() );
			if ( empty( $term_ids ) ) {
				continue;
			}
			wp_set_object_terms( $product_id, $term_ids, $taxonomy, false );
			$attr = new WC_Product_Attribute();
			$attr->set_id( wc_attribute_taxonomy_id_by_name( str_replace( 'pa_', '', $taxonomy ) ) );
			$attr->set_name( $taxonomy );
			$attr->set_options( $term_ids );
			$attr->set_position( $position++ );
			$attr->set_visible( true );
			$attr->set_variation( ! empty( $spec['used_for_variations'] ) );
			$wc_attributes[] = $attr;
		}
		$product->set_attributes( $wc_attributes );
		$product->save();

		return array( 'success' => true, 'attributes' => array_keys( $attribute_specs ) );
	}

	private function apply_manifest_args_to_product_data( $product_data, $args ) {
		$product_data = is_array( $product_data ) ? $product_data : array();
		$args         = is_array( $args ) ? $args : array();

		if ( ! empty( $args['dynamic_variant_manifest'] ) && is_array( $args['dynamic_variant_manifest'] ) ) {
			$product_data['dynamic_variant_manifest'] = $this->sanitize_dynamic_variant_manifest( $args['dynamic_variant_manifest'] );
		}
		if ( ! empty( $args['attribute_term_labels'] ) && is_array( $args['attribute_term_labels'] ) ) {
			$product_data['attribute_term_labels'] = $this->sanitize_attribute_term_labels( $args['attribute_term_labels'] );
		}

		return $product_data;
	}

	private function sanitize_dynamic_variant_manifest( $manifest ) {
		$manifest = is_array( $manifest ) ? $manifest : array();
		$out      = array(
			'source'           => isset( $manifest['source'] ) ? sanitize_text_field( (string) $manifest['source'] ) : 'llm_browser',
			'attribute_labels' => isset( $manifest['attribute_labels'] ) && is_array( $manifest['attribute_labels'] ) ? $this->sanitize_attribute_term_labels( $manifest['attribute_labels'] ) : array(),
			'variants'         => array(),
		);

		foreach ( isset( $manifest['variants'] ) && is_array( $manifest['variants'] ) ? $manifest['variants'] : array() as $variant ) {
			$variant = is_array( $variant ) ? $variant : array();
			$attrs   = array();
			foreach ( isset( $variant['attributes'] ) && is_array( $variant['attributes'] ) ? $variant['attributes'] : array() as $taxonomy => $value ) {
				$taxonomy = $this->normalize_taxonomy( $taxonomy );
				$value    = sanitize_title( (string) $value );
				if ( '' !== $taxonomy && '' !== $value ) {
					$attrs[ $taxonomy ] = $value;
				}
			}
			if ( empty( $attrs ) ) {
				continue;
			}

			$gallery = array();
			foreach ( isset( $variant['gallery_images'] ) && is_array( $variant['gallery_images'] ) ? $variant['gallery_images'] : array() as $image ) {
				$url = is_array( $image ) && isset( $image['url'] ) ? esc_url_raw( (string) $image['url'] ) : esc_url_raw( (string) $image );
				if ( '' !== $url ) {
					$gallery[] = array( 'url' => $url, 'source' => 'dynamic_browser_manifest' );
				}
			}
			$featured = array();
			if ( ! empty( $variant['featured_image'] ) ) {
				$url = is_array( $variant['featured_image'] ) && isset( $variant['featured_image']['url'] ) ? esc_url_raw( (string) $variant['featured_image']['url'] ) : esc_url_raw( (string) $variant['featured_image'] );
				if ( '' !== $url ) {
					$featured = array( 'url' => $url, 'source' => 'dynamic_browser_manifest' );
				}
			}

			$out['variants'][] = array(
				'attributes'       => $attrs,
				'attribute_labels' => isset( $variant['attribute_labels'] ) && is_array( $variant['attribute_labels'] ) ? $this->sanitize_variant_attribute_labels( $variant['attribute_labels'], $attrs ) : array(),
				'featured_image'   => $featured,
				'gallery_images'   => $gallery,
				'confidence'       => isset( $variant['confidence'] ) ? max( 0, min( 1, floatval( $variant['confidence'] ) ) ) : 0.95,
				'event'            => isset( $variant['event'] ) ? sanitize_text_field( (string) $variant['event'] ) : 'variant_selection',
			);
		}

		return $out;
	}

	private function sanitize_variant_attribute_labels( $labels, $attrs ) {
		$out = array();
		foreach ( is_array( $labels ) ? $labels : array() as $taxonomy => $label ) {
			$taxonomy = $this->normalize_taxonomy( $taxonomy );
			if ( '' === $taxonomy || ! isset( $attrs[ $taxonomy ] ) ) {
				continue;
			}
			$slug  = sanitize_title( (string) $attrs[ $taxonomy ] );
			$label = $this->sanitize_label_value( $label, $slug );
			if ( '' !== $slug && '' !== $label ) {
				$out[ $taxonomy ][ $slug ] = $label;
			}
		}
		return $out;
	}

	private function sanitize_attribute_term_labels( $labels ) {
		$out = array();
		foreach ( is_array( $labels ) ? $labels : array() as $taxonomy => $terms ) {
			$taxonomy = $this->normalize_taxonomy( $taxonomy );
			if ( '' === $taxonomy || ! is_array( $terms ) ) {
				continue;
			}
			foreach ( $terms as $slug => $label ) {
				$slug  = sanitize_title( (string) $slug );
				$label = $this->sanitize_label_value( $label, $slug );
				if ( '' !== $slug && '' !== $label ) {
					$out[ $taxonomy ][ $slug ] = $label;
				}
			}
		}
		return $out;
	}

	private function sanitize_label_value( $label, $slug = '' ) {
		if ( is_array( $label ) ) {
			$slug = sanitize_title( (string) $slug );
			if ( '' !== $slug && isset( $label[ $slug ] ) && ! is_array( $label[ $slug ] ) ) {
				return sanitize_text_field( (string) $label[ $slug ] );
			}
			foreach ( $label as $value ) {
				if ( ! is_array( $value ) ) {
					$value = sanitize_text_field( (string) $value );
					if ( '' !== $value ) {
						return $value;
					}
				}
			}
			return '';
		}
		return sanitize_text_field( (string) $label );
	}

	private function recreate_source_variations( $product_id, $product_data, $media_by_url, $mode ) {
		$product = wc_get_product( $product_id );
		if ( ! $product || ! $product->is_type( 'variable' ) ) {
			return array( 'success' => false, 'error' => 'Ciljni proizvod nije variable.' );
		}
		if ( 'update_existing' !== $mode ) {
			foreach ( (array) $product->get_children() as $child_id ) {
				wp_delete_post( intval( $child_id ), true );
			}
		}

		$source_variations = isset( $product_data['source_variations'] ) && is_array( $product_data['source_variations'] ) ? $product_data['source_variations'] : array();
		if ( empty( $source_variations ) ) {
			return array( 'success' => false, 'error' => 'Source nema structured varijacije.' );
		}

		$created = array();
		$variant_media_manifest = $this->variant_media_manifest_by_signature( $product_data );
		foreach ( $source_variations as $index => $source_variation ) {
			$attrs = isset( $source_variation['attributes'] ) && is_array( $source_variation['attributes'] ) ? $source_variation['attributes'] : array();
			$attrs = $this->normalize_variation_attribute_map( $attrs );
			if ( empty( $attrs ) ) {
				continue;
			}

			$variation = new WC_Product_Variation();
			$variation->set_parent_id( $product_id );
			$variation->set_attributes( $attrs );
			$price = isset( $source_variation['price'] ) ? (string) $source_variation['price'] : '';
			if ( '' !== $price ) {
				$variation->set_regular_price( $price );
			}
			$variation->set_manage_stock( false );
			$variation->set_stock_status( ! empty( $source_variation['is_in_stock'] ) ? 'instock' : 'outofstock' );
			$variation->set_status( ! empty( $source_variation['variation_is_active'] ) ? 'publish' : 'private' );
			if ( ! empty( $source_variation['backorders_allowed'] ) ) {
				$variation->set_backorders( 'yes' );
			}
			if ( ! empty( $source_variation['variation_description'] ) ) {
				$variation->set_description( wp_kses_post( (string) $source_variation['variation_description'] ) );
			}
			$signature = $this->variant_media->variation_signature( $attrs );
			$variation_media = isset( $variant_media_manifest[ $signature ] )
				? $this->variant_media->attachment_ids_for_variant_media( $variant_media_manifest[ $signature ], $media_by_url )
				: $this->variant_media->attachment_ids_for_source_variation( $source_variation, $media_by_url );
			if ( ! empty( $variation_media['featured_id'] ) ) {
				$variation->set_image_id( intval( $variation_media['featured_id'] ) );
			}
			$variation->save();
			$this->variant_media->update_variation_gallery_meta( intval( $variation->get_id() ), $variation_media );
			$created[] = intval( $variation->get_id() );
		}

		if ( empty( $created ) ) {
			return array( 'success' => false, 'error' => 'Nijedna source varijacija nije kreirana.' );
		}
		return array( 'success' => true, 'variation_ids' => $created );
	}

	private function apply_variation_skus_after_archive( $product_id, $product_data ) {
		$product = wc_get_product( $product_id );
		if ( ! $product || ! $product->is_type( 'variable' ) ) {
			return;
		}
		$source_variations = isset( $product_data['source_variations'] ) && is_array( $product_data['source_variations'] ) ? array_values( $product_data['source_variations'] ) : array();
		$children          = array_values( (array) $product->get_children() );
		foreach ( $children as $index => $variation_id ) {
			$source = isset( $source_variations[ $index ] ) && is_array( $source_variations[ $index ] ) ? $source_variations[ $index ] : array();
			$sku    = isset( $source['sku'] ) ? trim( (string) $source['sku'] ) : '';
			if ( '' === $sku ) {
				continue;
			}
			$variation = wc_get_product( intval( $variation_id ) );
			if ( $variation && $variation->is_type( 'variation' ) ) {
				try {
					$variation->set_sku( $sku );
					$variation->save();
				} catch ( Exception $e ) {
					continue;
				}
			}
		}
	}

	private function archive_replaced_product( $product_id, $sku ) {
		$product = wc_get_product( $product_id );
		if ( ! $product ) {
			return array( 'success' => false, 'error' => 'Stari proizvod za archive ne postoji.' );
		}
		foreach ( (array) $product->get_children() as $child_id ) {
			$variation = wc_get_product( intval( $child_id ) );
			if ( $variation && $variation->is_type( 'variation' ) ) {
				try {
					$variation->set_sku( 'archived-' . sanitize_title( $sku ) . '-' . intval( $child_id ) );
				} catch ( Exception $e ) {
					// Continue archiving even if an old variation has a duplicate SKU edge case.
				}
				$variation->set_status( 'private' );
				$variation->save();
			}
		}
		try {
			$product->set_sku( 'archived-' . sanitize_title( $sku ) . '-' . $product_id );
		} catch ( Exception $e ) {
			return array( 'success' => false, 'error' => 'Ne mogu da oslobodim SKU starog proizvoda: ' . $e->getMessage() );
		}
		$product->set_status( 'draft' );
		$product->save();
		$this->sync_parent( $product_id );
		return array( 'success' => true );
	}

	private function verify_clone( $product_id, $source, $expected_categories ) {
		$product = wc_get_product( $product_id );
		if ( ! $product || ! $product->is_type( 'variable' ) ) {
			return array( 'success' => false, 'issues' => array( 'product_not_variable' ) );
		}
		$product_data      = isset( $source['product'] ) && is_array( $source['product'] ) ? $source['product'] : array();
		$source_variations = isset( $product_data['source_variations'] ) && is_array( $product_data['source_variations'] ) ? $product_data['source_variations'] : array();
		$issues            = array();
		if ( count( (array) $product->get_children() ) !== count( $source_variations ) ) {
			$issues[] = 'variation_count_mismatch';
		}
		if ( ! has_post_thumbnail( $product_id ) ) {
			$issues[] = 'missing_featured_image';
		}
		if ( count( $product->get_gallery_image_ids() ) < max( 0, min( count( isset( $product_data['images'] ) ? (array) $product_data['images'] : array() ) - 1, 1 ) ) ) {
			$issues[] = 'missing_gallery_images';
		}
		if ( ! empty( $expected_categories ) ) {
			$current = array_values( array_unique( array_map( 'intval', (array) $product->get_category_ids() ) ) );
			$expected = array_values( array_unique( array_map( 'intval', $expected_categories ) ) );
			sort( $current );
			sort( $expected );
			if ( $current !== $expected ) {
				$issues[] = 'category_preservation_failed';
			}
		}
		$variation_gallery = array();
		$expected_variant_media = $this->variant_media_manifest_by_signature( $product_data );
		foreach ( array_values( (array) $product->get_children() ) as $index => $variation_id ) {
			$variation = wc_get_product( intval( $variation_id ) );
			if ( ! $variation || ! $variation->is_type( 'variation' ) ) {
				$issues[] = 'invalid_variation_' . intval( $variation_id );
				continue;
			}
			if ( '' === (string) $variation->get_regular_price() ) {
				$issues[] = 'variation_missing_price_' . intval( $variation_id );
			}
			if ( intval( $variation->get_image_id() ) <= 0 ) {
				$issues[] = 'variation_missing_image_' . intval( $variation_id );
			}
			$source_variation = isset( $source_variations[ $index ] ) && is_array( $source_variations[ $index ] ) ? $source_variations[ $index ] : array();
			$expected_gallery = $this->variant_media->expected_gallery_count( $source_variation );
			$signature = $this->variant_media->variation_signature( $variation->get_attributes() );
			if ( isset( $expected_variant_media[ $signature ]['gallery_images'] ) && is_array( $expected_variant_media[ $signature ]['gallery_images'] ) ) {
				$expected_gallery = max( $expected_gallery, count( $expected_variant_media[ $signature ]['gallery_images'] ) );
			}
			$gallery_ids      = get_post_meta( intval( $variation_id ), Niwa_AI_Admin_Partner_Product_Variant_Media::META_GALLERY_IMAGE_IDS, true );
			$gallery_ids      = is_array( $gallery_ids ) ? array_values( array_filter( array_map( 'intval', $gallery_ids ) ) ) : array();
			if ( $expected_gallery > 1 && count( $gallery_ids ) < $expected_gallery ) {
				$issues[] = 'variation_gallery_missing_' . intval( $variation_id );
			}
			$variation_gallery[] = array(
				'variation_id'   => intval( $variation_id ),
				'expected_count' => intval( $expected_gallery ),
				'actual_count'   => count( $gallery_ids ),
			);
		}
		$matrix = $this->verify_variable_matrix( $product, $product_data );
		if ( empty( $matrix['success'] ) && ! empty( $matrix['issues'] ) ) {
			$issues = array_merge( $issues, $matrix['issues'] );
		}

		return array(
			'success'             => empty( $issues ),
			'issues'              => $issues,
			'product_id'          => $product_id,
			'variation_count'     => count( (array) $product->get_children() ),
			'expected_variations' => count( $source_variations ),
			'gallery_count'       => count( $product->get_gallery_image_ids() ),
			'variation_gallery'   => $variation_gallery,
			'matrix'              => $matrix,
		);
	}

	private function variant_media_manifest_by_signature( $product_data ) {
		$map = array();
		foreach ( isset( $product_data['variant_media'] ) && is_array( $product_data['variant_media'] ) ? $product_data['variant_media'] : array() as $media ) {
			$media = is_array( $media ) ? $media : array();
			$signature = isset( $media['signature'] ) ? (string) $media['signature'] : '';
			if ( '' === $signature && isset( $media['attributes'] ) && is_array( $media['attributes'] ) ) {
				$signature = $this->variant_media->variation_signature( $media['attributes'] );
			}
			if ( '' !== $signature ) {
				$map[ $signature ] = $media;
			}
		}
		return $map;
	}

	private function build_attribute_specs( $product_data ) {
		$specs = array();
		$source_variations = isset( $product_data['source_variations'] ) && is_array( $product_data['source_variations'] ) ? $product_data['source_variations'] : array();
		$variation_options = $this->variation_attribute_options_map( $product_data );
		$variation_value_options = array();
		foreach ( $source_variations as $variation ) {
			foreach ( isset( $variation['attributes'] ) ? (array) $variation['attributes'] : array() as $taxonomy => $value ) {
				$taxonomy = $this->normalize_taxonomy( $taxonomy );
				if ( '' === $taxonomy ) {
					continue;
				}
				if ( ! isset( $specs[ $taxonomy ] ) ) {
					$specs[ $taxonomy ] = array( 'label' => $this->taxonomy_label( $taxonomy ), 'values' => array(), 'used_for_variations' => true );
				}
				if ( '' !== (string) $value ) {
					$value = sanitize_title( (string) $value );
					$specs[ $taxonomy ]['values'][] = $value;
					$variation_value_options[ $taxonomy ][] = $value;
				}
			}
		}
		foreach ( $variation_options as $taxonomy => $values ) {
			if ( ! isset( $specs[ $taxonomy ] ) ) {
				$specs[ $taxonomy ] = array( 'label' => $this->taxonomy_label( $taxonomy ), 'values' => array(), 'used_for_variations' => true );
			}
			if ( empty( $variation_value_options[ $taxonomy ] ) ) {
				$specs[ $taxonomy ]['values'] = array_merge( $specs[ $taxonomy ]['values'], $values );
			}
		}
		$variation_semantic_groups = array();
		foreach ( $specs as $taxonomy => $spec ) {
			if ( empty( $spec['used_for_variations'] ) ) {
				continue;
			}
			$semantic = $this->semantic_attribute_group( $taxonomy );
			if ( '' !== $semantic ) {
				$variation_semantic_groups[ $semantic ] = true;
			}
		}
		foreach ( isset( $product_data['attributes'] ) ? (array) $product_data['attributes'] : array() as $attribute ) {
			$name = isset( $attribute['name'] ) ? trim( (string) $attribute['name'] ) : '';
			if ( '' === $name ) {
				continue;
			}
			$taxonomy = $this->resolve_taxonomy_from_label( $name );
			if ( '' === $taxonomy ) {
				$taxonomy = 'pa_' . sanitize_title( $name );
			}
			$semantic = $this->semantic_attribute_group( $taxonomy );
			if ( '' !== $semantic && isset( $variation_semantic_groups[ $semantic ] ) ) {
				continue;
			}
			if ( isset( $specs[ $taxonomy ] ) || ! $this->is_safe_non_variation_attribute( $name ) ) {
				continue;
			}
			if ( ! isset( $specs[ $taxonomy ] ) ) {
				$specs[ $taxonomy ] = array( 'label' => $name, 'values' => array(), 'used_for_variations' => false );
			}
			foreach ( isset( $attribute['values'] ) ? (array) $attribute['values'] : array() as $value ) {
				$specs[ $taxonomy ]['values'][] = (string) $value;
			}
		}
		foreach ( $specs as $taxonomy => $spec ) {
			$specs[ $taxonomy ]['values'] = array_values( array_unique( array_filter( array_map( 'strval', $spec['values'] ) ) ) );
			if ( ! empty( $spec['used_for_variations'] ) && empty( $specs[ $taxonomy ]['values'] ) ) {
				unset( $specs[ $taxonomy ] );
			}
		}
		return $specs;
	}

	private function variation_attribute_options_map( $product_data ) {
		$map = array();
		foreach ( isset( $product_data['variation_attribute_options'] ) ? (array) $product_data['variation_attribute_options'] : array() as $definition ) {
			$taxonomy = isset( $definition['attribute'] ) ? $this->normalize_taxonomy( $definition['attribute'] ) : '';
			if ( '' === $taxonomy || empty( $definition['options'] ) || ! is_array( $definition['options'] ) ) {
				continue;
			}
			if ( ! isset( $map[ $taxonomy ] ) ) {
				$map[ $taxonomy ] = array();
			}
			foreach ( $definition['options'] as $option ) {
				$option = sanitize_title( (string) $option );
				if ( '' !== $option ) {
					$map[ $taxonomy ][] = $option;
				}
			}
		}
		foreach ( isset( $product_data['variants'] ) ? (array) $product_data['variants'] : array() as $variant ) {
			$taxonomy = isset( $variant['attribute'] ) ? $this->normalize_taxonomy( $variant['attribute'] ) : '';
			if ( '' === $taxonomy || empty( $variant['options'] ) || ! is_array( $variant['options'] ) ) {
				continue;
			}
			if ( ! isset( $map[ $taxonomy ] ) ) {
				$map[ $taxonomy ] = array();
			}
			foreach ( $variant['options'] as $option ) {
				$option = sanitize_title( (string) $option );
				if ( '' !== $option ) {
					$map[ $taxonomy ][] = $option;
				}
			}
		}
		foreach ( $map as $taxonomy => $values ) {
			$map[ $taxonomy ] = array_values( array_unique( array_filter( $values ) ) );
		}
		return $map;
	}

	private function normalize_variation_attribute_map( $attrs ) {
		$normalized = array();
		foreach ( (array) $attrs as $taxonomy => $value ) {
			$taxonomy = $this->normalize_taxonomy( $taxonomy );
			if ( '' === $taxonomy ) {
				continue;
			}
			$normalized[ $taxonomy ] = sanitize_title( (string) $value );
		}
		return $normalized;
	}

	private function is_safe_non_variation_attribute( $name ) {
		$name = trim( (string) $name );
		if ( '' === $name ) {
			return false;
		}
		if ( preg_match( '/^[\d\s.,;:\/+\-]+$/u', $name ) ) {
			return false;
		}
		$letters = preg_replace( '/[^[:alpha:]]/u', '', $name );
		return strlen( (string) $letters ) >= 2;
	}

	private function verify_variable_matrix( $product, $product_data ) {
		$issues = array();
		$parent_attrs = array();
		$semantic_groups = array();
		foreach ( (array) $product->get_attributes() as $attribute ) {
			if ( ! is_a( $attribute, 'WC_Product_Attribute' ) || ! $attribute->get_variation() ) {
				continue;
			}
			$name = (string) $attribute->get_name();
			$parent_attrs[ $name ] = array(
				'options' => array_values( array_filter( array_map( 'strval', (array) $attribute->get_options() ) ) ),
				'slugs'   => $this->parent_attribute_option_slugs( $attribute ),
				'label'   => function_exists( 'wc_attribute_label' ) ? wc_attribute_label( $name, $product ) : $name,
			);
			$semantic = $this->semantic_attribute_group( $name );
			if ( '' !== $semantic ) {
				if ( ! isset( $semantic_groups[ $semantic ] ) ) {
					$semantic_groups[ $semantic ] = array();
				}
				$semantic_groups[ $semantic ][] = $name;
			}
		}
		if ( empty( $parent_attrs ) ) {
			$issues[] = 'matrix_missing_parent_variation_attributes';
		}
		foreach ( $semantic_groups as $semantic => $names ) {
			if ( count( array_unique( $names ) ) > 1 ) {
				$issues[] = 'matrix_duplicate_semantic_attribute_' . $semantic . '_' . implode( '_', array_map( 'sanitize_key', $names ) );
			}
		}
		foreach ( $parent_attrs as $name => $definition ) {
			if ( empty( $definition['options'] ) ) {
				$issues[] = 'matrix_parent_attribute_has_no_options_' . sanitize_key( $name );
			}
		}
		foreach ( (array) $product->get_children() as $variation_id ) {
			$variation = wc_get_product( intval( $variation_id ) );
			if ( ! $variation || ! $variation->is_type( 'variation' ) ) {
				continue;
			}
			$attrs = $variation->get_attributes();
			foreach ( $parent_attrs as $name => $_definition ) {
				if ( ! array_key_exists( $name, $attrs ) && ! metadata_exists( 'post', intval( $variation_id ), 'attribute_' . $name ) ) {
					$issues[] = 'matrix_variation_missing_attribute_' . intval( $variation_id ) . '_' . sanitize_key( $name );
				}
			}
			foreach ( $attrs as $name => $_value ) {
				if ( ! isset( $parent_attrs[ $name ] ) ) {
					$issues[] = 'matrix_variation_unexpected_attribute_' . intval( $variation_id ) . '_' . sanitize_key( $name );
					continue;
				}
				$value = sanitize_title( (string) $_value );
				if ( '' !== $value && ! in_array( $value, (array) $parent_attrs[ $name ]['slugs'], true ) ) {
					$issues[] = 'matrix_variation_value_missing_from_parent_' . intval( $variation_id ) . '_' . sanitize_key( $name ) . '_' . sanitize_key( $value );
				}
			}
		}

		$expected = array();
		foreach ( isset( $product_data['source_variations'] ) ? (array) $product_data['source_variations'] : array() as $source_variation ) {
			foreach ( isset( $source_variation['attributes'] ) ? (array) $source_variation['attributes'] : array() as $name => $_value ) {
				$name = $this->normalize_taxonomy( $name );
				if ( '' !== $name ) {
					$expected[ $name ] = true;
				}
			}
		}
		foreach ( $expected as $name => $_ ) {
			if ( ! isset( $parent_attrs[ $name ] ) ) {
				$issues[] = 'matrix_source_attribute_missing_on_parent_' . sanitize_key( $name );
			}
		}

		return array(
			'success' => empty( $issues ),
			'issues'  => array_values( array_unique( $issues ) ),
			'parent_variation_attributes' => array_keys( $parent_attrs ),
		);
	}

	private function parent_attribute_option_slugs( $attribute ) {
		$slugs = array();
		if ( ! is_a( $attribute, 'WC_Product_Attribute' ) ) {
			return $slugs;
		}
		$name = (string) $attribute->get_name();
		foreach ( (array) $attribute->get_options() as $option ) {
			$slug = '';
			if ( 0 === strpos( $name, 'pa_' ) && is_numeric( $option ) ) {
				$term = get_term( intval( $option ), $name );
				if ( $term && ! is_wp_error( $term ) ) {
					$slug = (string) $term->slug;
				}
			}
			if ( '' === $slug ) {
				$slug = sanitize_title( (string) $option );
			}
			if ( '' !== $slug ) {
				$slugs[] = $slug;
			}
		}
		return array_values( array_unique( $slugs ) );
	}

	private function semantic_attribute_group( $name ) {
		$key = $this->normalize_label( str_replace( 'pa_', '', (string) $name ) );
		if ( in_array( $key, array( 'velicina', 'broj', 'br', 'size', 'sizes', 'shoe_size', 'shoesize', 'number' ), true ) ) {
			return 'size';
		}
		if ( in_array( $key, array( 'boja', 'color', 'colour', 'farben', 'farbe' ), true ) ) {
			return 'color';
		}
		return '';
	}

	private function ensure_attribute_taxonomy( $taxonomy, $label ) {
		$taxonomy = $this->normalize_taxonomy( $taxonomy );
		if ( taxonomy_exists( $taxonomy ) ) {
			return true;
		}
		$slug = preg_replace( '/^pa_/', '', $taxonomy );
		$existing = function_exists( 'wc_attribute_taxonomy_id_by_name' ) ? wc_attribute_taxonomy_id_by_name( $slug ) : 0;
		if ( ! $existing && function_exists( 'wc_create_attribute' ) ) {
			wc_create_attribute(
				array(
					'name'         => $label,
					'slug'         => $slug,
					'type'         => 'select',
					'order_by'     => 'menu_order',
					'has_archives' => false,
				)
			);
		}
		if ( ! taxonomy_exists( $taxonomy ) ) {
			register_taxonomy( $taxonomy, array( 'product' ), array( 'hierarchical' => false, 'show_ui' => false, 'query_var' => true, 'rewrite' => false ) );
		}
		return true;
	}

	private function ensure_terms( $taxonomy, $values, $label_overrides = array() ) {
		$term_ids = array();
		foreach ( (array) $values as $value ) {
			$value = trim( (string) $value );
			if ( '' === $value ) {
				continue;
			}
			$slug  = sanitize_title( $value );
			$label = isset( $label_overrides[ $slug ] ) ? (string) $label_overrides[ $slug ] : $this->label_normalizer->term_label( $value, $taxonomy );
			$term  = get_term_by( 'slug', $slug, $taxonomy );
			if ( $term && ! is_wp_error( $term ) ) {
				if ( '' !== $label && isset( $term->name ) && (string) $term->name !== $label && function_exists( 'wp_update_term' ) ) {
					wp_update_term( intval( $term->term_id ), $taxonomy, array( 'name' => $label ) );
				}
				$term_ids[] = intval( $term->term_id );
				continue;
			}
			$inserted = wp_insert_term( '' !== $label ? $label : $value, $taxonomy, array( 'slug' => $slug ) );
			if ( ! is_wp_error( $inserted ) ) {
				$term_ids[] = intval( $inserted['term_id'] );
			}
		}
		return array_values( array_unique( array_filter( $term_ids ) ) );
	}

	private function find_attachment_by_source_url( $url ) {
		$posts = get_posts(
			array(
				'post_type'      => 'attachment',
				'post_status'    => 'inherit',
				'posts_per_page' => 1,
				'fields'         => 'ids',
				'meta_query'     => array(
					array(
						'key'   => '_niwa_source_image_hash',
						'value' => sha1( $url ),
					),
				),
			)
		);
		return ! empty( $posts[0] ) ? intval( $posts[0] ) : 0;
	}

	private function source_variation_image_url( $source_variation ) {
		return $this->variant_media->source_variation_image_url( $source_variation );
	}

	private function sync_parent( $product_id ) {
		$product_id = intval( $product_id );
		if ( $product_id <= 0 ) {
			return;
		}
		if ( class_exists( 'WC_Product_Variable' ) && method_exists( 'WC_Product_Variable', 'sync' ) ) {
			WC_Product_Variable::sync( $product_id );
		}
		if ( function_exists( 'wc_delete_product_transients' ) ) {
			wc_delete_product_transients( $product_id );
		}
		if ( class_exists( 'Niwa_AI_Admin_Product_Management_Service' ) ) {
			$service = new Niwa_AI_Admin_Product_Management_Service();
			if ( method_exists( $service, 'reconcile_parent_attributes_from_variations' ) ) {
				$service->reconcile_parent_attributes_from_variations( $product_id );
			}
		}
		do_action( 'niwa_ai_index_upsert', $product_id, 'product', true );
	}

	private function finalize_clone_parent_matrix( $product_id, $product_data ) {
		$this->sync_parent( $product_id );
		$attributes_result = $this->sync_source_attributes( $product_id, $product_data );
		if ( empty( $attributes_result['success'] ) ) {
			return $attributes_result;
		}
		if ( function_exists( 'wc_delete_product_transients' ) ) {
			wc_delete_product_transients( intval( $product_id ) );
		}
		if ( function_exists( 'clean_post_cache' ) ) {
			clean_post_cache( intval( $product_id ) );
		}
		do_action( 'niwa_ai_index_upsert', intval( $product_id ), 'product', true );
		return array( 'success' => true );
	}

	private function normalize_taxonomy( $taxonomy ) {
		$taxonomy = sanitize_key( preg_replace( '/^attribute_/', '', (string) $taxonomy ) );
		return 0 === strpos( $taxonomy, 'pa_' ) ? $taxonomy : ( '' !== $taxonomy ? 'pa_' . $taxonomy : '' );
	}

	private function taxonomy_label( $taxonomy ) {
		$taxonomy = $this->normalize_taxonomy( $taxonomy );
		if ( function_exists( 'wc_attribute_label' ) ) {
			$label = wc_attribute_label( $taxonomy );
			if ( '' !== trim( (string) $label ) ) {
				return (string) $label;
			}
		}
		return trim( str_replace( array( 'pa_', '-', '_' ), ' ', $taxonomy ) );
	}

	private function resolve_taxonomy_from_label( $label ) {
		if ( ! function_exists( 'wc_get_attribute_taxonomies' ) ) {
			return '';
		}
		$needle = $this->normalize_label( $label );
		foreach ( (array) wc_get_attribute_taxonomies() as $attr ) {
			$candidates = array(
				isset( $attr->attribute_label ) ? (string) $attr->attribute_label : '',
				isset( $attr->attribute_name ) ? (string) $attr->attribute_name : '',
			);
			foreach ( $candidates as $candidate ) {
				if ( $needle === $this->normalize_label( $candidate ) ) {
					return 'pa_' . $attr->attribute_name;
				}
			}
		}
		return '';
	}

	private function normalize_label( $value ) {
		$value = trim( (string) $value );
		if ( function_exists( 'remove_accents' ) ) {
			$value = remove_accents( $value );
		}
		$value = mb_strtolower( $value );
		return preg_replace( '/[^a-z0-9]+/', '', $value );
	}

	private function canonical_image_key( $url ) {
		return $this->image_context->canonical_image_key( $url );
	}
}
