<?php
/**
 * The public-facing functionality of the plugin.
 *
 * Defines the plugin name, version, and hooks for enqueuing
 * the public-facing stylesheet and JavaScript.
 *
 * @package    Ai_Try_N_Buy
 * @subpackage Ai_Try_N_Buy/public
 * @author     Edu Brazeal <contact@edubrazeal.com>
 */
class Aitnb_Public {

	/**
	 * The ID of this plugin.
	 *
	 * @since    1.0.0
	 * @access   private
	 * @var      string    $plugin_name    The ID of this plugin.
	 */
	private $plugin_name;

	/**
	 * The version of this plugin.
	 *
	 * @since    1.0.0
	 * @access   private
	 * @var      string    $version    The current version of this plugin.
	 */
	private $version;

	/**
	 * Initialize the class and set its properties.
	 *
	 * @since    1.0.0
	 * @param    string    $plugin_name       The name of the plugin.
	 * @param    string    $version    The version of this plugin.
	 */
	public function __construct( $plugin_name, $version ) {
		$this->plugin_name = $plugin_name;
		$this->version     = $version;

		$this->register_ajax_handlers();
		add_filter( 'script_loader_tag', array( $this, 'add_module_type_to_model_viewer' ), 10, 3 );
	}

	/**
	 * Adds the 'type="module"' attribute to the model-viewer script tag.
	 *
	 * @since 1.0.0
	 * @param string $tag    The <script> tag for the enqueued script.
	 * @param string $handle The script's handle.
	 * @param string $src    The script's source URL.
	 * @return string The modified script tag.
	 */
	public function add_module_type_to_model_viewer( $tag, $handle, $src ) {
		if ( $this->plugin_name . '-model-viewer' === $handle ) {
			// phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
			$tag = '<script type="module" src="' . esc_url( $src ) . '" id="' . esc_attr( $handle ) . '-js"></script>';
		}
		return $tag;
	}

	/**
	 * Register the stylesheets for the public-facing side of the site.
	 *
	 * @since    1.0.0
	 */
	public function enqueue_styles() {
		if ( is_singular( 'product' ) ) {
			$fit_recommender_css_path = plugin_dir_path( __FILE__ ) . 'assets/css/fit-recommender-styles.css';

			wp_enqueue_style( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'assets/css/try-on-styles.css', array(), $this->version, 'all' );
			
			if ( file_exists( $fit_recommender_css_path ) ) {
				wp_enqueue_style( $this->plugin_name . '-fit-recommender', plugin_dir_url( __FILE__ ) . 'assets/css/fit-recommender-styles.css', array(), $this->version, 'all' );
			}
			
			wp_enqueue_style( $this->plugin_name . '-style-assistant', plugin_dir_url( __FILE__ ) . 'assets/css/style-assistant-styles.css', array(), $this->version, 'all' );
		}
	}

	/**
	 * Register the JavaScript for the public-facing side of the site.
	 *
	 * @since    1.0.0
	 */
	public function enqueue_scripts() {
		if ( is_singular( 'product' ) ) {
			global $post;
			
			$params = $this->get_script_data();
			$is_tryon_enabled = get_post_meta( $post->ID, '_aitnb_enable_tryon', true );

			if ( 'yes' === $is_tryon_enabled && ! empty( $params ) ) {
				$ar_mode = isset( $params['product']['ar_mode'] ) ? $params['product']['ar_mode'] : 'face';

				if ( 'face' === $ar_mode ) {
					$face_tracker_handle = $this->plugin_name . '-face-tracker';
					wp_enqueue_script( 'aframe', plugin_dir_url( __FILE__ ) . 'assets/vendor/aframe/aframe.min.js', array(), '1.5.0', false );
					wp_enqueue_script( 'mindar-face', plugin_dir_url( __FILE__ ) . 'assets/vendor/mindar/mindar-face-aframe.prod.js', array( 'aframe' ), '1.2.5', false );
					wp_enqueue_script( $face_tracker_handle, plugin_dir_url( __FILE__ ) . 'assets/js/face-tracker.js', array( 'jquery', 'aframe', 'mindar-face' ), $this->version, true );
					wp_localize_script( $face_tracker_handle, 'aitnb_params', $params );
				} else {
					$world_tracker_handle = $this->plugin_name . '-world-tracker';
					wp_enqueue_script( $this->plugin_name . '-model-viewer', plugin_dir_url( __FILE__ ) . 'assets/vendor/model-viewer/model-viewer.min.js', array(), '3.5.0', true );
					wp_enqueue_script( $world_tracker_handle, plugin_dir_url( __FILE__ ) . 'assets/js/world-tracker.js', array( 'jquery', $this->plugin_name . '-model-viewer' ), $this->version, true );
					wp_localize_script( $world_tracker_handle, 'aitnb_params', $params );
				}
			}
			
			wp_enqueue_script( $this->plugin_name . '-fit-recommender', plugin_dir_url( __FILE__ ) . 'assets/js/fit-recommender.js', array( 'jquery' ), $this->version, true );
			wp_enqueue_script( $this->plugin_name . '-style-assistant', plugin_dir_url( __FILE__ ) . 'assets/js/style-assistant.js', array( 'jquery' ), $this->version, true );

			wp_localize_script( $this->plugin_name . '-fit-recommender', 'aitnb_fit_params', $params );
			wp_localize_script( $this->plugin_name . '-style-assistant', 'aitnb_style_params', $params );
		}
	}

	/**
	 * Adds the container for the action buttons.
	 *
	 * @since    1.0.0
	 */
	public function add_action_buttons() {
		global $product;
		if ( ! is_a( $product, 'WC_Product' ) ) {
			return;
		}

		$is_tryon_enabled = get_post_meta( $product->get_id(), '_aitnb_enable_tryon', true );
		$is_fit_enabled   = get_post_meta( $product->get_id(), '_aitnb_enable_fit_recommender', true );

		if ( 'yes' === $is_tryon_enabled || 'yes' === $is_fit_enabled ) {
			include plugin_dir_path( __FILE__ ) . 'views/action-buttons-view.php';
		}
	}

	/**
	 * Adds the placeholder section for the AI Style Assistant.
	 *
	 * @since    1.0.0
	 */
	public function add_style_assistant_section() {
		global $product;
		if ( ! is_a( $product, 'WC_Product' ) ) {
			return;
		}
		$is_enabled = get_post_meta( $product->get_id(), '_aitnb_enable_style_assistant', true );
		if ( 'yes' === $is_enabled ) {
			require_once plugin_dir_path( __FILE__ ) . 'views/style-assistant-view.php';
		}
	}


	/**
	 * Gathers necessary data from PHP for the public JavaScript files.
	 *
	 * @since    1.0.0
	 * @access   private
	 * @return   array      An array of parameters for the scripts.
	 */
	private function get_script_data() {
		$product_id = get_the_ID();
		$product = wc_get_product( $product_id );

		if ( ! is_a( $product, 'WC_Product' ) ) {
			return array();
		}
		
		$asset_id   = get_post_meta( $product_id, '_aitnb_overlay_asset_id', true );
		$asset_url  = $asset_id ? wp_get_attachment_url( $asset_id ) : '';
		$item_type  = get_post_meta( $product_id, '_aitnb_item_type', true );
		$position   = get_post_meta( $product_id, '_aitnb_asset_position', true );
		$scale      = get_post_meta( $product_id, '_aitnb_asset_scale', true );
		$ar_mode    = get_post_meta( $product_id, '_aitnb_ar_mode', true );

		$position = wp_parse_args( (array) $position, array( 'x' => 0, 'y' => 0.10, 'z' => -0.5 ) );
		$scale    = ! empty( $scale ) ? $scale : ( str_ends_with( strtolower( $asset_url ), '.glb' ) ? '0.0015' : '0.3' );
		$ar_mode  = ! empty( $ar_mode ) ? $ar_mode : 'face';

		return array(
			'ajax_url'  => admin_url( 'admin-ajax.php' ),
			'nonce'     => wp_create_nonce( 'aitnb_public_nonce' ),
			'product'   => array(
				'id'        => $product_id,
				'name'      => $product->get_name(),
				'asset_url' => $asset_url,
				'item_type' => $item_type,
				'position'  => $position,
				'scale'     => $scale,
				'ar_mode'   => $ar_mode,
			),
			'i18n'      => array(
				'addAllToCart'           => __( 'Add All to Cart', 'virtual-ai-fit-and-style-assistant' ),
				'adding'                 => __( 'Adding...', 'virtual-ai-fit-and-style-assistant' ),
				'viewCart'               => __( 'View Cart', 'virtual-ai-fit-and-style-assistant' ),
				'selectAllOptions'       => __( 'Please select all product options.', 'virtual-ai-fit-and-style-assistant' ),
				'combinationUnavailable' => __( 'A selected combination of options is not available. Please try a different selection.', 'virtual-ai-fit-and-style-assistant' ),
				'errorOccurred'          => __( 'An error occurred.', 'virtual-ai-fit-and-style-assistant' ),
				'requestFailed'          => __( 'Request failed. Please check your connection and try again.', 'virtual-ai-fit-and-style-assistant' ),
				'analyzing'              => __( 'Analyzing... Please wait.', 'virtual-ai-fit-and-style-assistant' ),
				'initializingCamera'     => __( 'Initializing camera...', 'virtual-ai-fit-and-style-assistant' ),
				'noAssetDefined'         => __( 'Error: No try-on asset is defined for this product.', 'virtual-ai-fit-and-style-assistant' ),
		'cameraError'            => __( 'Error: Could not start camera. Please check permissions.', 'virtual-ai-fit-and-style-assistant' ),
				'noGlbModel'             => __( 'Error: A valid .glb model file is not configured for this product.', 'virtual-ai-fit-and-style-assistant' ),
			),
		);
	}

	/**
	 * Registers the AJAX handlers for public-facing features.
	 *
	 * @since 1.0.0
	 */
	public function register_ajax_handlers() {
		add_action( 'wp_ajax_nopriv_aitnb_get_fit_recommendation', array( $this, 'ajax_get_fit_recommendation' ) );
		add_action( 'wp_ajax_aitnb_get_fit_recommendation', array( $this, 'ajax_get_fit_recommendation' ) );
		add_action( 'wp_ajax_nopriv_aitnb_get_style_recommendations', array( $this, 'ajax_get_style_recommendations' ) );
		add_action( 'wp_ajax_aitnb_get_style_recommendations', array( $this, 'ajax_get_style_recommendations' ) );
		add_action( 'wp_ajax_nopriv_aitnb_add_style_products_to_cart', array( $this, 'ajax_add_style_products_to_cart' ) );
		add_action( 'wp_ajax_aitnb_add_style_products_to_cart', array( $this, 'ajax_add_style_products_to_cart' ) );
	}

	/**
	 * Handles AJAX request for AI Fit Recommendation.
	 *
	 * @since 1.0.0
	 */
	public function ajax_get_fit_recommendation() {
		check_ajax_referer( 'aitnb_public_nonce', 'nonce' );

		$product_id = isset( $_POST['product_id'] ) ? absint( $_POST['product_id'] ) : 0;
		if ( ! $product_id ) {
			wp_send_json_error( array( 'message' => __( 'Invalid product.', 'virtual-ai-fit-and-style-assistant' ) ) );
		}

		$size_chart_string = get_post_meta( $product_id, '_aitnb_size_chart', true );
		if ( empty( $size_chart_string ) ) {
			wp_send_json_error( array( 'message' => __( 'No size chart is available for this product.', 'virtual-ai-fit-and-style-assistant' ) ) );
		}

		$user_data = array();
		if ( isset( $_POST['user_data'] ) && is_array( $_POST['user_data'] ) ) {
			foreach ( $_POST['user_data'] as $key => $value ) {
				$user_data[ sanitize_key( $key ) ] = sanitize_text_field( wp_unslash( $value ) );
			}
		}

		if ( empty( $user_data ) ) {
			wp_send_json_error( array( 'message' => __( 'Please provide your measurements.', 'virtual-ai-fit-and-style-assistant' ) ) );
		}

		$unique_inputs_string = $product_id . $user_data['height'] . $user_data['weight'] . $user_data['fit_preference'];
		$transient_key        = 'aitnb_fit_rec_' . md5( $unique_inputs_string );

		$cached_recommendation = get_transient( $transient_key );

		if ( false !== $cached_recommendation ) {
			wp_send_json_success( array( 'recommendation' => wp_kses_post( $cached_recommendation ) ) );
			return;
		}

		$parsed_chart = array();
		$lines        = explode( "\n", trim( $size_chart_string ) );

		foreach ( $lines as $line ) {
			if ( strpos( $line, ':' ) !== false ) {
				list( $size, $measurements ) = explode( ':', $line, 2 );
				$parsed_chart[ trim( $size ) ] = trim( $measurements );
			}
		}

		if ( empty( $parsed_chart ) ) {
			wp_send_json_error( array( 'message' => __( 'The size chart for this product is not formatted correctly.', 'virtual-ai-fit-and-style-assistant' ) ) );
		}

		$options    = get_option( 'aitnb_settings' );
		$api_key    = isset( $options['gemini_api_key'] ) ? $options['gemini_api_key'] : '';
		$fit_model  = isset( $options['gemini_fit_model'] ) ? $options['gemf_model'] : 'gemini-2.5-flash-latest';

		if ( empty( $api_key ) ) {
			wp_send_json_error( array( 'message' => __( 'The API is not configured.', 'virtual-ai-fit-and-style-assistant' ) ) );
		}

		require_once plugin_dir_path( dirname( __FILE__ ) ) . 'services/class-gemini-fit-service.php';
		$service    = new Aitnb_Gemini_Fit_Service( $api_key, $fit_model );
		$response   = $service->get_fit_recommendation( $user_data, array( 'chart' => $parsed_chart ) );

		if ( is_wp_error( $response ) ) {
			wp_send_json_error( array( 'message' => $response->get_error_message() ) );
		}

		set_transient( $transient_key, $response, HOUR_IN_SECONDS );

		wp_send_json_success( array( 'recommendation' => wp_kses_post( $response ) ) );
	}

	/**
	 * Handles AJAX request for AI Style Assistant.
	 *
	 * This function now uses a caching layer (transients) to avoid
	 * making API calls on every page load.
	 *
	 * @since 1.0.0
	 */
	public function ajax_get_style_recommendations() {
		check_ajax_referer( 'aitnb_public_nonce', 'nonce' );

		$product_id = isset( $_POST['product_id'] ) ? absint( $_POST['product_id'] ) : 0;
		if ( ! $product_id ) {
			wp_send_json_error( array( 'message' => __( 'Invalid product.', 'virtual-ai-fit-and-style-assistant' ) ) );
		}

		$current_product = wc_get_product( $product_id );
		if ( ! $current_product ) {
			wp_send_json_error( array( 'message' => __( 'Product not found.', 'virtual-ai-fit-and-style-assistant' ) ) );
		}

		$original_product_data = $this->prepare_product_data_for_display( $current_product );

		$transient_key = 'aitnb_style_recs_' . $product_id;
		$cached_ids    = get_transient( $transient_key );

		if ( false !== $cached_ids && is_array( $cached_ids ) ) {
			$recommended_products = $this->prepare_products_for_display( $cached_ids );
			wp_send_json_success(
				array(
					'original_product' => $original_product_data,
					'products'         => $recommended_products,
				)
			);
			return;
		}

		$options = get_option( 'aitnb_settings' );
		$api_key = isset( $options['gemini_api_key'] ) ? $options['gemini_api_key'] : '';
		if ( empty( $api_key ) ) {
			wp_send_json_error( array( 'message' => __( 'The API is not configured.', 'virtual-ai-fit-and-style-assistant' ) ) );
		}

		$selected_categories = get_post_meta( $product_id, '_aitnb_style_assistant_categories', true );
		if ( empty( $selected_categories ) || ! is_array( $selected_categories ) ) {
			wp_send_json_success(
				array(
					'original_product' => $original_product_data,
					'products'         => array(),
				)
			);
			return;
		}

		$args = array(
			'post_type'      => 'product',
			'posts_per_page' => 50,
			'fields'         => 'ids',
		);
		$all_products    = new WP_Query( $args );
		$all_product_ids = $all_products->posts;
		$product_catalog = array();

		if ( ! empty( $all_product_ids ) ) {
			foreach ( $all_product_ids as $pid ) {
				if ( $pid === $product_id ) {
					continue;
				}

				$product_categories = wp_get_post_terms( $pid, 'product_cat', array( 'fields' => 'ids' ) );
				if ( is_wp_error( $product_categories ) ) {
					continue;
				}

				$has_matching_category = false;
				foreach ( $selected_categories as $selected_cat ) {
					if ( in_array( $selected_cat, $product_categories, true ) ) {
						$has_matching_category = true;
						break;
					}
				}

				if ( ! $has_matching_category ) {
					continue;
				}

				$product_obj = wc_get_product( $pid );
				if ( $product_obj ) {
					$product_catalog[] = array(
						'name' => $product_obj->get_name(),
						'sku'  => $product_obj->get_sku(),
					);
				}
			}
		}

		if ( empty( $product_catalog ) ) {
			wp_send_json_success(
				array(
					'original_product' => $original_product_data,
					'products'         => array(),
				)
			);
			return;
		}

		$style_model = isset( $options['gemini_style_model'] ) ? $options['gemini_style_model'] : 'gemini-2.5-pro-latest';
		require_once plugin_dir_path( dirname( __FILE__ ) ) . 'services/class-gemini-style-service.php';
		$service      = new Aitnb_Gemini_Style_Service( $api_key, $style_model );
		$product_data = array(
			'name' => $current_product->get_name(),
			'sku'  => $current_product->get_sku(),
		);
		$response     = $service->get_style_recommendations( $product_data, $product_catalog );

		if ( is_wp_error( $response ) ) {
			wp_send_json_error( array( 'message' => $response->get_error_message() ) );
		}

		$recommended_product_ids = array();
		if ( ! empty( $response ) ) {
			foreach ( $response as $sku ) {
				$rec_product_id = wc_get_product_id_by_sku( $sku );
				if ( $rec_product_id ) {
					$recommended_product_ids[] = $rec_product_id;
				}
			}
		}

		$frequency  = isset( $options['style_assistant_frequency'] ) ? $options['style_assistant_frequency'] : 'daily';
		$expiration = 'weekly' === $frequency ? WEEK_IN_SECONDS : DAY_IN_SECONDS;
		$expiration = 'twicedaily' === $frequency ? 12 * HOUR_IN_SECONDS : $expiration;

		set_transient( $transient_key, $recommended_product_ids, $expiration );

		$recommended_products = $this->prepare_products_for_display( $recommended_product_ids );
		wp_send_json_success(
			array(
				'original_product' => $original_product_data,
				'products'         => $recommended_products,
			)
		);
	}

	/**
	 * Handles AJAX request to add all style assistant products to the cart.
	 *
	 * @since 1.0.0
	 */
	public function ajax_add_style_products_to_cart() {
		check_ajax_referer( 'aitnb_public_nonce', 'nonce' );

		if ( ! isset( $_POST['products'] ) || ! is_array( $_POST['products'] ) ) {
			wp_send_json_error( array( 'message' => __( 'Invalid product data provided.', 'virtual-ai-fit-and-style-assistant' ) ) );
		}

		$products_to_add = isset( $_POST['products'] ) && is_array( $_POST['products'] ) ? $_POST['products'] : array();
		$added_count     = 0;

		foreach ( $products_to_add as $product_data ) {
			if ( ! is_array( $product_data ) ) {
				continue;
			}

			$product_id = isset( $product_data['product_id'] ) ? absint( wp_unslash( $product_data['product_id'] ) ) : 0;

			if ( $product_id <= 0 ) {
				continue;
			}

			$variation_id = isset( $product_data['variation_id'] ) ? absint( wp_unslash( $product_data['variation_id'] ) ) : 0;
			$attributes   = isset( $product_data['attributes'] ) && is_array( $product_data['attributes'] ) ? (array) $product_data['attributes'] : array();

			$sanitized_attributes = array();
			foreach ( $attributes as $key => $value ) {
				$sanitized_attributes[ sanitize_key( $key ) ] = sanitize_text_field( wp_unslash( $value ) );
			}

			$result = WC()->cart->add_to_cart( $product_id, 1, $variation_id, $sanitized_attributes );

			if ( false !== $result ) {
				$added_count++;
			}
		}

		if ( $added_count > 0 ) {
			wp_send_json_success(
				array(
					'message'  => sprintf(
						// translators: %d is the number of products added to the cart.
						_n( '%d item added to your cart.', '%d items added to your cart.', $added_count, 'virtual-ai-fit-and-style-assistant' ),
						$added_count
					),
					'cart_url' => wc_get_cart_url(),
				)
			);
		} else {
			wp_send_json_error( array( 'message' => __( 'Could not add items to the cart. Please ensure you have selected all required options.', 'virtual-ai-fit-and-style-assistant' ) ) );
		}
	}


	/**
	 * Helper function to convert an array of product IDs to displayable data.
	 *
	 * @param array $product_ids An array of WooCommerce product IDs.
	 * @return array An array of products formatted for JSON response.
	 */
	private function prepare_products_for_display( $product_ids ) {
		$formatted_products = array();
		if ( empty( $product_ids ) || ! is_array( $product_ids ) ) {
			return $formatted_products;
		}

		foreach ( $product_ids as $product_id ) {
			$product = wc_get_product( $product_id );
			if ( $product ) {
				$formatted_products[] = $this->prepare_product_data_for_display( $product );
			}
		}
		return $formatted_products;
	}

	/**
	 * Helper function to get all necessary data for a single product.
	 *
	 * @param WC_Product $product The WooCommerce product object.
	 * @return array An array of product data formatted for JSON response.
	 */
	private function prepare_product_data_for_display( $product ) {
		if ( ! is_a( $product, 'WC_Product' ) ) {
			return array();
		}

		$product_data = array(
			'id'        => $product->get_id(),
			'name'      => $product->get_name(),
			'price'     => $product->get_price_html(),
			'image_url' => wp_get_attachment_image_url( $product->get_image_id(), 'woocommerce_thumbnail' ),
			'link'      => $product->get_permalink(),
			'type'      => $product->get_type(),
		);

		if ( $product->is_type( 'variable' ) ) {
			$variations_data = array();
			$attributes      = array();

			$available_variations = $product->get_available_variations();

			foreach ( $available_variations as $variation ) {
				$variations_data[] = array(
					'id'         => $variation['variation_id'],
					'attributes' => $variation['attributes'],
					'price_html' => $variation['price_html'],
				);
			}

			foreach ( $product->get_variation_attributes() as $taxonomy => $terms ) {
				$taxonomy_obj = get_taxonomy( $taxonomy );
				$attributes[] = array(
					'name'  => wc_attribute_label( $taxonomy, $product ),
					'slug'  => $taxonomy,
					'terms' => $terms,
				);
			}

			$product_data['variations'] = $variations_data;
			$product_data['attributes'] = $attributes;
		}

		return $product_data;
	}
}
