<?php
/**
 * Static embedded-state parser for non-Woo partner variant media.
 *
 * @package Niwa_AI
 */

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

class Niwa_AI_Admin_Partner_Product_Static_Variant_Media_Parser {
	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 extract_from_html( $html, $base_url ) {
		$out = array(
			'source_variations' => array(),
			'images'            => array(),
			'warnings'          => array(),
			'source'            => '',
		);

		foreach ( $this->extract_json_candidates( $html ) as $candidate ) {
			$product = $this->find_product_like_object( $candidate );
			if ( ! is_array( $product ) ) {
				continue;
			}
			$parsed = $this->extract_from_product_object( $product, $base_url, 'embedded_variant_product_json' );
			if ( ! empty( $parsed['source_variations'] ) ) {
				return $parsed;
			}
		}

		$out['warnings'][] = 'No embedded variant media JSON source was detected.';
		return $out;
	}

	public function extract_from_product_object( $product, $base_url, $source = 'embedded_variant_product_json' ) {
		return $this->parse_product_object( is_array( $product ) ? $product : array(), $base_url, $source );
	}

	private function extract_json_candidates( $html ) {
		$candidates = array();
		if ( ! is_string( $html ) || '' === $html ) {
			return $candidates;
		}

		if ( preg_match_all( '#<script\b[^>]*>(.*?)</script>#is', $html, $matches ) ) {
			foreach ( $matches[1] as $script ) {
				$script = trim( html_entity_decode( (string) $script, ENT_QUOTES | ENT_HTML5, 'UTF-8' ) );
				if ( '' === $script || ( false === strpos( $script, 'variant' ) && false === strpos( $script, 'Variant' ) ) ) {
					continue;
				}
				$decoded = $this->decode_jsonish_script( $script );
				if ( null !== $decoded ) {
					$candidates[] = $decoded;
				}
			}
		}

		return $candidates;
	}

	private function decode_jsonish_script( $script ) {
		$script = trim( (string) $script );
		if ( '' === $script ) {
			return null;
		}

		$direct = json_decode( $script, true );
		if ( JSON_ERROR_NONE === json_last_error() ) {
			return $direct;
		}

		foreach ( array(
			'/window\.__NUXT__\s*=\s*(\{.*\})\s*;?\s*$/s',
			'/window\.__INITIAL_STATE__\s*=\s*(\{.*\})\s*;?\s*$/s',
			'/var\s+meta\s*=\s*(\{.*\})\s*;?\s*$/s',
			'/ShopifyAnalytics\.meta\s*=\s*(\{.*\})\s*;?\s*$/s',
		) as $pattern ) {
			if ( preg_match( $pattern, $script, $m ) ) {
				$decoded = json_decode( trim( $m[1] ), true );
				if ( JSON_ERROR_NONE === json_last_error() ) {
					return $decoded;
				}
			}
		}

		return null;
	}

	private function find_product_like_object( $data, $depth = 0 ) {
		if ( $depth > 8 || ! is_array( $data ) ) {
			return null;
		}
		if ( isset( $data['variants'] ) && is_array( $data['variants'] ) && ( isset( $data['images'] ) || isset( $data['media'] ) || isset( $data['options'] ) ) ) {
			return $data;
		}
		if ( isset( $data['product'] ) && is_array( $data['product'] ) ) {
			$found = $this->find_product_like_object( $data['product'], $depth + 1 );
			if ( is_array( $found ) ) {
				return $found;
			}
		}
		foreach ( $data as $value ) {
			if ( is_array( $value ) ) {
				$found = $this->find_product_like_object( $value, $depth + 1 );
				if ( is_array( $found ) ) {
					return $found;
				}
			}
		}
		return null;
	}

	private function parse_product_object( $product, $base_url, $source = 'embedded_variant_product_json' ) {
		$options       = $this->option_names( $product );
		$media_by_id   = $this->media_by_id( $product, $base_url );
		$product_images = array_values( $media_by_id );
		$variations    = array();

		foreach ( isset( $product['variants'] ) ? (array) $product['variants'] : array() as $variant ) {
			if ( ! is_array( $variant ) ) {
				continue;
			}
			$attrs = array();
			for ( $i = 1; $i <= 3; $i++ ) {
				$value = isset( $variant[ 'option' . $i ] ) ? trim( (string) $variant[ 'option' . $i ] ) : '';
				if ( '' === $value ) {
					continue;
				}
				$name           = isset( $options[ $i - 1 ] ) ? $options[ $i - 1 ] : 'option_' . $i;
				$attrs[ 'pa_' . sanitize_title( $name ) ] = sanitize_title( $value );
			}

			$image_url = $this->variant_image_url( $variant, $media_by_id, $base_url );
			if ( '' === $image_url && ! empty( $product_images[0]['url'] ) ) {
				$image_url = (string) $product_images[0]['url'];
			}
			$gallery   = $this->variant_gallery_images( $variant, $media_by_id, $image_url );
			if ( empty( $attrs ) && '' === $image_url ) {
				continue;
			}

			$variations[] = array(
				'source_variation_id'  => intval( isset( $variant['id'] ) ? $variant['id'] : 0 ),
				'attributes'           => $attrs,
				'display_price'        => isset( $variant['price'] ) ? $this->normalize_price( $variant['price'] ) : '',
				'display_regular_price'=> isset( $variant['compare_at_price'] ) && '' !== (string) $variant['compare_at_price'] ? $this->normalize_price( $variant['compare_at_price'] ) : ( isset( $variant['price'] ) ? $this->normalize_price( $variant['price'] ) : '' ),
				'price'                => isset( $variant['price'] ) ? $this->normalize_price( $variant['price'] ) : '',
				'sku'                  => isset( $variant['sku'] ) ? sanitize_text_field( (string) $variant['sku'] ) : '',
				'is_in_stock'          => ! array_key_exists( 'available', $variant ) || ! empty( $variant['available'] ),
				'is_purchasable'       => ! array_key_exists( 'available', $variant ) || ! empty( $variant['available'] ),
				'variation_is_active'  => true,
				'variation_is_visible' => true,
				'backorders_allowed'   => false,
				'variation_description'=> '',
				'image'                => array( 'url' => $image_url, 'full_src' => $image_url, 'src' => $image_url, 'srcset' => '', 'alt' => '', 'title' => '' ),
				'gallery_images'       => $gallery,
				'media_confidence'     => 0.8,
				'media_evidence'       => array( 'source' => $source ),
			);
		}

		return array(
			'source_variations' => $variations,
			'images'            => $product_images,
			'warnings'          => empty( $variations ) ? array( 'Embedded product JSON had no usable variants.' ) : array(),
			'source'            => $source,
		);
	}

	private function option_names( $product ) {
		$out = array();
		foreach ( isset( $product['options'] ) ? (array) $product['options'] : array() as $option ) {
			if ( is_array( $option ) && isset( $option['name'] ) ) {
				$out[] = sanitize_text_field( (string) $option['name'] );
			} elseif ( is_string( $option ) ) {
				$out[] = sanitize_text_field( $option );
			}
		}
		return $out;
	}

	private function media_by_id( $product, $base_url ) {
		$out = array();
		foreach ( array( 'media', 'images' ) as $key ) {
			foreach ( isset( $product[ $key ] ) ? (array) $product[ $key ] : array() as $index => $image ) {
				$url = $this->absolute_url( $this->image_url_from_mixed( $image ), $base_url );
				if ( '' === $url || ! $this->image_context->is_product_image_url( $url ) ) {
					continue;
				}
				$id = '';
				if ( is_array( $image ) ) {
					$id = isset( $image['id'] ) ? (string) $image['id'] : ( isset( $image['media_id'] ) ? (string) $image['media_id'] : '' );
				}
				if ( '' === $id ) {
					$id = (string) $index;
				}
				$out[ $id ] = array( 'url' => $url, 'recommended_role' => empty( $out ) ? 'featured' : 'gallery', 'source' => 'embedded_product_media' );
			}
		}
		return $out;
	}

	private function variant_image_url( $variant, $media_by_id, $base_url ) {
		foreach ( array( 'featured_image', 'image', 'featured_media' ) as $key ) {
			if ( empty( $variant[ $key ] ) ) {
				continue;
			}
			$url = $this->absolute_url( $this->image_url_from_mixed( $variant[ $key ] ), $base_url );
			if ( '' !== $url ) {
				return $url;
			}
		}
		foreach ( array( 'image_id', 'featured_media_id', 'media_id' ) as $key ) {
			$id = isset( $variant[ $key ] ) ? (string) $variant[ $key ] : '';
			if ( '' !== $id && ! empty( $media_by_id[ $id ]['url'] ) ) {
				return (string) $media_by_id[ $id ]['url'];
			}
		}
		return '';
	}

	private function variant_gallery_images( $variant, $media_by_id, $featured_url ) {
		$gallery = array();
		foreach ( array( 'media_ids', 'image_ids', 'gallery_media_ids' ) as $key ) {
			foreach ( isset( $variant[ $key ] ) ? (array) $variant[ $key ] : array() as $id ) {
				$id = (string) $id;
				if ( ! empty( $media_by_id[ $id ]['url'] ) ) {
					$url = (string) $media_by_id[ $id ]['url'];
					if ( '' !== $featured_url && $url === $featured_url ) {
						continue;
					}
					$gallery[] = array( 'url' => $url, 'source' => 'embedded_variant_gallery' );
				}
			}
		}
		return $gallery;
	}

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

	private function absolute_url( $url, $base_url ) {
		$url = trim( (string) $url );
		if ( '' === $url ) {
			return '';
		}
		if ( preg_match( '#^https?://#i', $url ) ) {
			return esc_url_raw( $url );
		}
		$base = wp_parse_url( $base_url );
		if ( empty( $base['scheme'] ) || empty( $base['host'] ) ) {
			return '';
		}
		if ( 0 === strpos( $url, '//' ) ) {
			return esc_url_raw( $base['scheme'] . ':' . $url );
		}
		$root = $base['scheme'] . '://' . $base['host'] . ( ! empty( $base['port'] ) ? ':' . $base['port'] : '' );
		if ( 0 === strpos( $url, '/' ) ) {
			return esc_url_raw( $root . $url );
		}
		$path = isset( $base['path'] ) ? preg_replace( '#/[^/]*$#', '/', $base['path'] ) : '/';
		return esc_url_raw( $root . $path . $url );
	}

	private function normalize_price( $price ) {
		if ( is_numeric( $price ) && floatval( $price ) > 999 ) {
			return rtrim( rtrim( number_format( floatval( $price ) / 100, 2, '.', '' ), '0' ), '.' );
		}
		return (string) $price;
	}
}
