<?php
/**
 * Normalized per-variation media model for partner product clones.
 *
 * @package Niwa_AI
 */

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

class Niwa_AI_Admin_Partner_Product_Variant_Media {
	const META_GALLERY_IMAGE_IDS   = '_niwa_variation_gallery_image_ids';
	const META_GALLERY_SOURCE_URLS = '_niwa_variation_gallery_source_urls';
	const META_MEDIA_SIGNATURE     = '_niwa_variation_media_signature';

	private $image_context;

	public function __construct( $image_context = null ) {
		$this->image_context = $image_context instanceof Niwa_AI_Admin_Partner_Product_Image_Context
			? $image_context
			: new Niwa_AI_Admin_Partner_Product_Image_Context();
	}

	public function normalize_product_data( $product_data ) {
		$product_data = is_array( $product_data ) ? $product_data : array();
		$variations   = isset( $product_data['source_variations'] ) && is_array( $product_data['source_variations'] ) ? $product_data['source_variations'] : array();

		$variant_media = array();
		foreach ( $variations as $index => $variation ) {
			$media = $this->media_for_source_variation( $variation );
			if ( empty( $media['gallery_images'] ) ) {
				continue;
			}
			$attrs = isset( $variation['attributes'] ) && is_array( $variation['attributes'] ) ? $variation['attributes'] : array();
			$variant_media[] = array(
				'index'            => intval( $index ),
				'signature'        => $this->variation_signature( $attrs ),
				'attributes'       => $attrs,
				'featured_image'   => $media['featured_image'],
				'gallery_images'   => $media['gallery_images'],
				'media_confidence' => isset( $variation['media_confidence'] ) ? floatval( $variation['media_confidence'] ) : 0.85,
				'media_evidence'   => isset( $variation['media_evidence'] ) && is_array( $variation['media_evidence'] ) ? $variation['media_evidence'] : array( 'source' => 'source_variation_payload' ),
			);
		}

		$variant_media = $this->enrich_variant_media_from_product_images(
			$variant_media,
			isset( $product_data['images'] ) && is_array( $product_data['images'] ) ? $product_data['images'] : array()
		);
		$product_data['variant_media'] = array_values( $variant_media );
		$product_data = $this->apply_dynamic_variant_manifest( $product_data );
		$product_data['images']        = $this->collect_all_images( $product_data );
		return $product_data;
	}

	public function apply_dynamic_variant_manifest( $product_data ) {
		$product_data = is_array( $product_data ) ? $product_data : array();
		$manifest     = isset( $product_data['dynamic_variant_manifest'] ) && is_array( $product_data['dynamic_variant_manifest'] ) ? $product_data['dynamic_variant_manifest'] : array();
		if ( empty( $manifest['variants'] ) || ! is_array( $manifest['variants'] ) ) {
			return $product_data;
		}

		$variant_media = isset( $product_data['variant_media'] ) && is_array( $product_data['variant_media'] ) ? array_values( $product_data['variant_media'] ) : array();
		$source_variations = isset( $product_data['source_variations'] ) && is_array( $product_data['source_variations'] ) ? $product_data['source_variations'] : array();
		$by_signature  = array();
		foreach ( $variant_media as $index => $media ) {
			$signature = isset( $media['signature'] ) ? (string) $media['signature'] : '';
			if ( '' !== $signature ) {
				$by_signature[ $signature ] = $index;
			}
		}

		foreach ( $manifest['variants'] as $index => $variant ) {
			$variant = is_array( $variant ) ? $variant : array();
			$attrs   = isset( $variant['attributes'] ) && is_array( $variant['attributes'] ) ? $this->normalize_attribute_map( $variant['attributes'] ) : array();
			if ( empty( $attrs ) ) {
				continue;
			}
			$attrs     = $this->complete_manifest_attrs_from_source_variations( $attrs, $source_variations );
			$signature = $this->variation_signature( $attrs );
			$gallery   = $this->normalize_manifest_gallery( $variant );
			if ( empty( $gallery ) ) {
				continue;
			}

			$media = array(
				'index'            => intval( $index ),
				'signature'        => $signature,
				'attributes'       => $attrs,
				'featured_image'   => isset( $gallery[0] ) ? $gallery[0] : array(),
				'gallery_images'   => $gallery,
				'media_confidence' => isset( $variant['confidence'] ) ? max( 0, min( 1, floatval( $variant['confidence'] ) ) ) : 0.95,
				'media_evidence'   => array(
					array(
						'source' => 'dynamic_browser_manifest',
						'event'  => isset( $variant['event'] ) ? sanitize_text_field( (string) $variant['event'] ) : 'variant_selection',
					),
				),
			);

			if ( isset( $by_signature[ $signature ] ) ) {
				$existing_index = intval( $by_signature[ $signature ] );
				$existing_count = count( isset( $variant_media[ $existing_index ]['gallery_images'] ) ? (array) $variant_media[ $existing_index ]['gallery_images'] : array() );
				if ( count( $gallery ) >= $existing_count ) {
					$variant_media[ $existing_index ] = $media;
				}
			} else {
				$by_signature[ $signature ] = count( $variant_media );
				$variant_media[]            = $media;
			}
		}

		$product_data['variant_media'] = array_values( $variant_media );
		return $product_data;
	}

	private function complete_manifest_attrs_from_source_variations( $attrs, $source_variations ) {
		$attrs = is_array( $attrs ) ? $attrs : array();
		foreach ( (array) $source_variations as $source_variation ) {
			$source_attrs = isset( $source_variation['attributes'] ) && is_array( $source_variation['attributes'] ) ? $this->normalize_attribute_map( $source_variation['attributes'] ) : array();
			if ( empty( $source_attrs ) ) {
				continue;
			}
			$matches = true;
			foreach ( $attrs as $taxonomy => $value ) {
				if ( ! array_key_exists( $taxonomy, $source_attrs ) || (string) $source_attrs[ $taxonomy ] !== (string) $value ) {
					$matches = false;
					break;
				}
			}
			if ( $matches ) {
				return $source_attrs;
			}
		}
		return $attrs;
	}

	public function collect_all_images( $product_data ) {
		$product_data = is_array( $product_data ) ? $product_data : array();
		$title        = isset( $product_data['title'] ) ? (string) $product_data['title'] : '';
		$images       = array();

		foreach ( isset( $product_data['images'] ) && is_array( $product_data['images'] ) ? $product_data['images'] : array() as $image ) {
			$url = isset( $image['url'] ) ? esc_url_raw( (string) $image['url'] ) : '';
			$this->append_image( $images, $url, isset( $image['recommended_role'] ) ? (string) $image['recommended_role'] : 'gallery', isset( $image['source'] ) ? (string) $image['source'] : 'product_images', $title );
		}

		foreach ( isset( $product_data['variant_media'] ) && is_array( $product_data['variant_media'] ) ? $product_data['variant_media'] : array() as $variant_media ) {
			foreach ( isset( $variant_media['gallery_images'] ) && is_array( $variant_media['gallery_images'] ) ? $variant_media['gallery_images'] : array() as $image ) {
				$url = isset( $image['url'] ) ? esc_url_raw( (string) $image['url'] ) : '';
				$this->append_image( $images, $url, 'variation_gallery', isset( $image['source'] ) ? (string) $image['source'] : 'variant_media', $title );
			}
		}

		return array_values( $images );
	}

	public function media_for_source_variation( $source_variation ) {
		$source_variation = is_array( $source_variation ) ? $source_variation : array();
		$gallery          = array();
		$primary          = $this->source_variation_image_url( $source_variation );

		if ( '' !== $primary ) {
			$this->append_image( $gallery, $primary, 'featured', 'source_variation_image', isset( $source_variation['sku'] ) ? (string) $source_variation['sku'] : '' );
		}

		foreach ( $this->extract_gallery_candidates( $source_variation ) as $url ) {
			$this->append_image( $gallery, $url, 'variation_gallery', 'source_variation_gallery', isset( $source_variation['sku'] ) ? (string) $source_variation['sku'] : '' );
		}

		$gallery = array_values( $gallery );
		return array(
			'featured_image' => isset( $gallery[0] ) ? $gallery[0] : array(),
			'gallery_images' => $gallery,
		);
	}

	public function attachment_ids_for_source_variation( $source_variation, $media_by_url ) {
		$media       = $this->media_for_source_variation( $source_variation );
		$featured_id = 0;
		$gallery_ids = array();
		$source_urls = array();

		foreach ( $media['gallery_images'] as $index => $image ) {
			$url = isset( $image['url'] ) ? (string) $image['url'] : '';
			$key = $this->image_context->canonical_image_key( $url );
			if ( '' === $key || empty( $media_by_url[ $key ] ) ) {
				continue;
			}
			$attachment_id = intval( $media_by_url[ $key ] );
			if ( 0 === $index && $featured_id <= 0 ) {
				$featured_id = $attachment_id;
			}
			$gallery_ids[] = $attachment_id;
			$source_urls[] = esc_url_raw( $url );
		}

		$attrs = isset( $source_variation['attributes'] ) && is_array( $source_variation['attributes'] ) ? $source_variation['attributes'] : array();
		return array(
			'featured_id' => $featured_id,
			'gallery_ids' => array_values( array_unique( array_filter( array_map( 'intval', $gallery_ids ) ) ) ),
			'source_urls' => array_values( array_unique( array_filter( $source_urls ) ) ),
			'signature'   => $this->variation_signature( $attrs ),
		);
	}

	public function attachment_ids_for_variant_media( $variant_media, $media_by_url ) {
		$variant_media = is_array( $variant_media ) ? $variant_media : array();
		$gallery       = isset( $variant_media['gallery_images'] ) && is_array( $variant_media['gallery_images'] ) ? $variant_media['gallery_images'] : array();
		$featured_id   = 0;
		$gallery_ids   = array();
		$source_urls   = array();

		foreach ( $gallery as $index => $image ) {
			$url = isset( $image['url'] ) ? (string) $image['url'] : '';
			$key = $this->image_context->canonical_image_key( $url );
			if ( '' === $key || empty( $media_by_url[ $key ] ) ) {
				continue;
			}
			$attachment_id = intval( $media_by_url[ $key ] );
			if ( 0 === $index && $featured_id <= 0 ) {
				$featured_id = $attachment_id;
			}
			$gallery_ids[] = $attachment_id;
			$source_urls[] = esc_url_raw( $url );
		}

		return array(
			'featured_id' => $featured_id,
			'gallery_ids' => array_values( array_unique( array_filter( array_map( 'intval', $gallery_ids ) ) ) ),
			'source_urls' => array_values( array_unique( array_filter( $source_urls ) ) ),
			'signature'   => isset( $variant_media['signature'] ) ? (string) $variant_media['signature'] : '',
		);
	}

	public function update_variation_gallery_meta( $variation_id, $media ) {
		$variation_id = intval( $variation_id );
		if ( $variation_id <= 0 ) {
			return;
		}
		$gallery_ids = isset( $media['gallery_ids'] ) && is_array( $media['gallery_ids'] ) ? array_values( array_unique( array_filter( array_map( 'intval', $media['gallery_ids'] ) ) ) ) : array();
		$source_urls = isset( $media['source_urls'] ) && is_array( $media['source_urls'] ) ? array_values( array_unique( array_filter( array_map( 'esc_url_raw', $media['source_urls'] ) ) ) ) : array();
		$signature   = isset( $media['signature'] ) ? (string) $media['signature'] : '';

		if ( empty( $gallery_ids ) ) {
			delete_post_meta( $variation_id, self::META_GALLERY_IMAGE_IDS );
			delete_post_meta( $variation_id, self::META_GALLERY_SOURCE_URLS );
			delete_post_meta( $variation_id, self::META_MEDIA_SIGNATURE );
			return;
		}

		update_post_meta( $variation_id, self::META_GALLERY_IMAGE_IDS, $gallery_ids );
		update_post_meta( $variation_id, self::META_GALLERY_SOURCE_URLS, $source_urls );
		update_post_meta( $variation_id, self::META_MEDIA_SIGNATURE, $signature );
	}

	public function expected_gallery_count( $source_variation ) {
		$media = $this->media_for_source_variation( $source_variation );
		return count( isset( $media['gallery_images'] ) ? (array) $media['gallery_images'] : array() );
	}

	public function variation_signature( $attrs ) {
		$parts = array();
		foreach ( (array) $attrs as $key => $value ) {
			$key = sanitize_key( preg_replace( '/^attribute_/', '', (string) $key ) );
			if ( '' === $key ) {
				continue;
			}
			$parts[] = $key . '=' . ( '' === (string) $value ? '*' : sanitize_title( (string) $value ) );
		}
		sort( $parts );
		return implode( '|', $parts );
	}

	public function source_variation_image_url( $source_variation ) {
		$image = isset( $source_variation['image'] ) && is_array( $source_variation['image'] ) ? $source_variation['image'] : array();
		foreach ( array( 'full_src', 'originalSrc', 'original_src', 'url', 'src' ) as $key ) {
			if ( ! empty( $image[ $key ] ) ) {
				return esc_url_raw( (string) $image[ $key ] );
			}
		}
		return '';
	}

	private function normalize_manifest_gallery( $variant ) {
		$gallery = array();
		foreach ( array( 'featured_image', 'image' ) as $key ) {
			if ( empty( $variant[ $key ] ) ) {
				continue;
			}
			$url = $this->image_url_from_mixed( $variant[ $key ] );
			if ( '' !== $url ) {
				$this->append_image( $gallery, $url, 'featured', 'dynamic_browser_manifest', isset( $variant['signature'] ) ? (string) $variant['signature'] : '' );
				break;
			}
		}
		foreach ( isset( $variant['gallery_images'] ) && is_array( $variant['gallery_images'] ) ? $variant['gallery_images'] : array() as $image ) {
			$url = $this->image_url_from_mixed( $image );
			if ( '' !== $url ) {
				$this->append_image( $gallery, $url, 'variation_gallery', 'dynamic_browser_manifest', isset( $variant['signature'] ) ? (string) $variant['signature'] : '' );
			}
		}
		return array_values( $gallery );
	}

	private function normalize_attribute_map( $attrs ) {
		$normalized = array();
		foreach ( (array) $attrs as $key => $value ) {
			$key = sanitize_key( preg_replace( '/^attribute_/', '', (string) $key ) );
			if ( '' === $key ) {
				continue;
			}
			$key = 0 === strpos( $key, 'pa_' ) ? $key : 'pa_' . $key;
			$normalized[ $key ] = sanitize_title( (string) $value );
		}
		return $normalized;
	}

	private function enrich_variant_media_from_product_images( $variant_media, $product_images ) {
		if ( empty( $variant_media ) || empty( $product_images ) ) {
			return $variant_media;
		}

		foreach ( $variant_media as $media_index => $media ) {
			$featured_url = isset( $media['featured_image']['url'] ) ? (string) $media['featured_image']['url'] : '';
			$family       = $this->image_family_key( $featured_url );
			if ( '' === $family ) {
				continue;
			}
			foreach ( $product_images as $image ) {
				$url = isset( $image['url'] ) ? esc_url_raw( (string) $image['url'] ) : '';
				if ( '' === $url || $this->image_family_key( $url ) !== $family ) {
					continue;
				}
				$this->append_image(
					$variant_media[ $media_index ]['gallery_images'],
					$url,
					'variation_gallery',
					'product_gallery_family_match',
					isset( $media['signature'] ) ? (string) $media['signature'] : ''
				);
			}
			if ( count( $variant_media[ $media_index ]['gallery_images'] ) > count( (array) $media['gallery_images'] ) ) {
				$variant_media[ $media_index ]['media_evidence'][] = array(
					'source' => 'product_gallery_family_match',
					'family' => $family,
				);
			}
		}

		return $variant_media;
	}

	private function image_family_key( $url ) {
		$path = (string) wp_parse_url( $url, PHP_URL_PATH );
		$base = strtolower( (string) pathinfo( $path, PATHINFO_FILENAME ) );
		$base = preg_replace( '/-\d+x\d+$/', '', $base );
		$base = preg_replace( '/([_-])\d+$/', '', $base );
		return trim( (string) $base );
	}

	private function extract_gallery_candidates( $source_variation ) {
		$candidates = array();
		foreach ( array( 'gallery_images', 'variation_gallery_images', 'variation_gallery', 'additional_images', 'media' ) as $key ) {
			if ( empty( $source_variation[ $key ] ) ) {
				continue;
			}
			foreach ( (array) $source_variation[ $key ] as $image ) {
				$url = $this->image_url_from_mixed( $image );
				if ( '' !== $url ) {
					$candidates[] = $url;
				}
			}
		}
		if ( ! empty( $source_variation['image']['srcset'] ) ) {
			$url = $this->image_context->srcset_best_url( (string) $source_variation['image']['srcset'] );
			if ( '' !== $url ) {
				$candidates[] = $url;
			}
		}
		return $candidates;
	}

	private function image_url_from_mixed( $image ) {
		if ( is_string( $image ) ) {
			return esc_url_raw( $image );
		}
		if ( ! is_array( $image ) ) {
			return '';
		}
		foreach ( array( 'full_src', 'originalSrc', 'original_src', 'url', 'src', 'preview_image', 'image' ) as $key ) {
			if ( empty( $image[ $key ] ) ) {
				continue;
			}
			if ( is_array( $image[ $key ] ) ) {
				$nested = $this->image_url_from_mixed( $image[ $key ] );
				if ( '' !== $nested ) {
					return $nested;
				}
			} elseif ( is_string( $image[ $key ] ) ) {
				return esc_url_raw( $image[ $key ] );
			}
		}
		return '';
	}

	private function append_image( &$images, $url, $role, $source, $title ) {
		$url = esc_url_raw( (string) $url );
		if ( '' === $url || ! $this->image_context->is_product_image_url( $url ) ) {
			return;
		}
		$key = $this->image_context->canonical_image_key( $url );
		if ( '' === $key ) {
			return;
		}
		foreach ( $images as $existing ) {
			$existing_url = isset( $existing['url'] ) ? (string) $existing['url'] : '';
			if ( '' !== $existing_url && $this->image_context->canonical_image_key( $existing_url ) === $key ) {
				return;
			}
		}
		$images[ $key ] = array(
			'url'                => $url,
			'recommended_role'   => $role,
			'alt_text_suggested' => (string) $title,
			'source'             => $source,
		);
	}
}
