<?php
/**
 * AJAX handlers.
 *
 * @package SKYNSMFA_Smart_Favorites
 */

declare( strict_types=1 );

namespace SKYNSMFA\Wishlist;

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


final class Ajax {
	/**
	 * Singleton instance.
	 *
	 * @var Ajax|null
	 */
	private static $instance = null;

	/**
	 * Nonce action.
	 *
	 * @var string
	 */
	private $nonce_action = 'skynsmfa_wishlist_nonce';

	/**
	 * Get singleton instance.
	 *
	 * @return Ajax
	 */
	public static function instance(): Ajax {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}

		return self::$instance;
	}

	/**
	 * Constructor.
	 */
	private function __construct() {
		add_action( 'wp_ajax_skynsmfa_add_to_wishlist', array( $this, 'add_to_wishlist' ) );
		add_action( 'wp_ajax_nopriv_skynsmfa_add_to_wishlist', array( $this, 'add_to_wishlist' ) );

		add_action( 'wp_ajax_skynsmfa_remove_from_wishlist', array( $this, 'remove_from_wishlist' ) );
		add_action( 'wp_ajax_nopriv_skynsmfa_remove_from_wishlist', array( $this, 'remove_from_wishlist' ) );

		add_action( 'wp_ajax_skynsmfa_create_wishlist', array( $this, 'create_wishlist' ) );
		add_action( 'wp_ajax_nopriv_skynsmfa_create_wishlist', array( $this, 'create_wishlist' ) );

		add_action( 'wp_ajax_skynsmfa_delete_wishlist', array( $this, 'delete_wishlist' ) );
		add_action( 'wp_ajax_nopriv_skynsmfa_delete_wishlist', array( $this, 'delete_wishlist' ) );

		add_action( 'wp_ajax_skynsmfa_rename_wishlist', array( $this, 'rename_wishlist' ) );
		add_action( 'wp_ajax_nopriv_skynsmfa_rename_wishlist', array( $this, 'rename_wishlist' ) );

		add_action( 'wp_ajax_skynsmfa_get_wishlist', array( $this, 'get_wishlist' ) );
		add_action( 'wp_ajax_nopriv_skynsmfa_get_wishlist', array( $this, 'get_wishlist' ) );

		add_action( 'wp_ajax_skynsmfa_move_to_cart', array( $this, 'move_to_cart' ) );
		add_action( 'wp_ajax_nopriv_skynsmfa_move_to_cart', array( $this, 'move_to_cart' ) );

		add_action( 'wp_ajax_skynsmfa_move_multiple_to_cart', array( $this, 'move_multiple_to_cart' ) );
		add_action( 'wp_ajax_nopriv_skynsmfa_move_multiple_to_cart', array( $this, 'move_multiple_to_cart' ) );

		add_action( 'wp_ajax_skynsmfa_add_all_to_cart', array( $this, 'add_all_to_cart' ) );
		add_action( 'wp_ajax_nopriv_skynsmfa_add_all_to_cart', array( $this, 'add_all_to_cart' ) );
	}

	/**
	 * Rate limit check for wishlist AJAX.
	 *
	 * @param string $slug Action slug.
	 * @return bool True if request may proceed.
	 */
	private function check_rate_limit( string $slug ): bool {
		$settings = get_option( 'skynsmfa_settings', array() );
		$max      = isset( $settings['skynsmfa_rate_limit_per_min'] ) ? absint( $settings['skynsmfa_rate_limit_per_min'] ) : 0;
		if ( $max <= 0 ) {
			$max = 120;
		}

		return Rate_Limit::instance()->allow( $slug, $max, 60 );
	}

	/**
	 * Ensure WooCommerce session is initialized for AJAX requests.
	 *
	 * @return void
	 */
	private function ensure_session(): void {
		if ( ! function_exists( 'WC' ) || ! WC()->session ) {
			return;
		}

		if ( ! WC()->session->has_session() ) {
			WC()->session->set_customer_session_cookie( true );
		}
	}

	/**
	 * Block AJAX when wishlist features are disabled globally.
	 *
	 * @return void
	 */
	private function ensure_feature_enabled(): void {
		if ( ! Plugin::is_wishlist_enabled() ) {
			wp_send_json_error(
				array(
					'message' => __( 'Wishlist features are currently disabled.', 'skynet-smart-favorites' ),
				),
				403
			);
		}
	}

	/**
	 * Block bulk cart AJAX without Pro.
	 *
	 * @return void
	 */
	private function ensure_pro_bulk_cart(): void {
		if ( ! Feature_Gate::can_bulk_cart() ) {
			wp_send_json_error(
				array(
					'message' => __( 'Bulk cart actions require SkyNet Smart Favorites Pro.', 'skynet-smart-favorites' ),
				),
				403
			);
		}
	}

	/**
	 * Add item to wishlist (session-backed skeleton).
	 *
	 * @return void
	 */
	public function add_to_wishlist(): void {
		$this->ensure_session();
		$this->ensure_feature_enabled();

		check_ajax_referer( $this->nonce_action, 'nonce' );

		if ( ! $this->check_rate_limit( 'add' ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Too many requests. Please wait a moment.', 'skynet-smart-favorites' ),
				),
				429
			);
		}

		$product_id    = isset( $_POST['product_id'] ) ? absint( wp_unslash( $_POST['product_id'] ) ) : 0;
		$variation_id  = isset( $_POST['variation_id'] ) ? absint( wp_unslash( $_POST['variation_id'] ) ) : 0;
		$qty           = isset( $_POST['qty'] ) ? absint( wp_unslash( $_POST['qty'] ) ) : 1;
		$wishlist_key  = isset( $_POST['wishlist_key'] ) ? sanitize_text_field( wp_unslash( $_POST['wishlist_key'] ) ) : 'default';

		$settings = get_option( 'skynsmfa_settings', array() );
		if ( ! is_array( $settings ) ) {
			$settings = array();
		}
		if ( 'yes' !== ( $settings['skynsmfa_multiple_enable'] ?? 'yes' ) ) {
			$wishlist_key = 'default';
		}

		if ( $product_id <= 0 ) {
			wp_send_json_error(
				array(
					'message' => __( 'Invalid product.', 'skynet-smart-favorites' ),
				)
			);
		}

		$context = isset( $_POST['context'] ) ? sanitize_text_field( wp_unslash( (string) $_POST['context'] ) ) : '';
		$product = wc_get_product( $product_id );
		if ( $product && $product->is_type( 'variable' ) && $variation_id <= 0 && 'single' === $context ) {
			wp_send_json_error(
				array(
					'message' => __( 'Please choose product options (color, size, etc.) before adding to your wishlist.', 'skynet-smart-favorites' ),
				)
			);
		}

		$data = Session::instance()->add_item( $product_id, max( 1, $qty ), $wishlist_key, $variation_id );

		Session::instance()->set_last_wishlist_key( $wishlist_key );

		/**
		 * Fires after a product is added to wishlist.
		 *
		 * @param int    $product_id Product ID.
		 * @param string $wishlist_key Wishlist key.
		 */
		do_action( 'skynsmfa_wishlist_added', $product_id, $wishlist_key );

		wp_send_json_success(
			array(
				'owner'      => Session::instance()->get_owner(),
				'data'       => $data,
				'item_count' => Session::count_items_from_data( $data ),
			)
		);
	}

	/**
	 * Remove item from wishlist (session-backed skeleton).
	 *
	 * @return void
	 */
	public function remove_from_wishlist(): void {
		$this->ensure_session();
		$this->ensure_feature_enabled();

		check_ajax_referer( $this->nonce_action, 'nonce' );

		if ( ! $this->check_rate_limit( 'remove' ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Too many requests. Please wait a moment.', 'skynet-smart-favorites' ),
				),
				429
			);
		}

		$product_id   = isset( $_POST['product_id'] ) ? absint( wp_unslash( $_POST['product_id'] ) ) : 0;
		$wishlist_key = isset( $_POST['wishlist_key'] ) ? sanitize_text_field( wp_unslash( $_POST['wishlist_key'] ) ) : 'default';

		if ( $product_id <= 0 ) {
			wp_send_json_error(
				array(
					'message' => __( 'Invalid product.', 'skynet-smart-favorites' ),
				)
			);
		}

		$resolved_key = Session::instance()->resolve_remove_list_key( $product_id, $wishlist_key );
		if ( '' === $resolved_key ) {
			wp_send_json_error(
				array(
					'message' => __( 'This product is not in your wishlist.', 'skynet-smart-favorites' ),
				)
			);
		}

		$data = Session::instance()->remove_item( $product_id, $resolved_key );

		/**
		 * Fires after a product is removed from wishlist.
		 *
		 * @param int    $product_id Product ID.
		 * @param string $wishlist_key Wishlist key.
		 */
		do_action( 'skynsmfa_wishlist_removed', $product_id, $resolved_key );

		wp_send_json_success(
			array(
				'owner'      => Session::instance()->get_owner(),
				'data'       => $data,
				'item_count' => Session::count_items_from_data( $data ),
			)
		);
	}

	/**
	 * Create a new wishlist list.
	 *
	 * @return void
	 */
	public function create_wishlist(): void {
		$this->ensure_session();
		$this->ensure_feature_enabled();

		check_ajax_referer( $this->nonce_action, 'nonce' );

		if ( ! $this->check_rate_limit( 'create_list' ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Too many requests. Please wait a moment.', 'skynet-smart-favorites' ),
				),
				429
			);
		}

		$settings = get_option( 'skynsmfa_settings', array() );
		if ( ! is_array( $settings ) ) {
			$settings = array();
		}
		if ( 'yes' !== ( $settings['skynsmfa_multiple_enable'] ?? 'yes' ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Multiple wishlists are disabled.', 'skynet-smart-favorites' ),
				)
			);
		}

		$list_name = isset( $_POST['list_name'] ) ? sanitize_text_field( wp_unslash( $_POST['list_name'] ) ) : '';

		if ( '' === $list_name ) {
			wp_send_json_error(
				array(
					'message' => __( 'Please provide a wishlist name.', 'skynet-smart-favorites' ),
				)
			);
		}

		if ( Session::instance()->list_display_name_exists( $list_name ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'A list with this name already exists. Please choose a different name.', 'skynet-smart-favorites' ),
				)
			);
		}

		$data     = Session::instance()->get_data();
		$base_key = 'custom:' . sanitize_title( $list_name );
		$key      = $base_key;

		if ( isset( $data[ $key ] ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'A list with this name already exists. Please choose a different name.', 'skynet-smart-favorites' ),
				)
			);
		}

		$data[ $key ] = array();
		Session::instance()->set_data( $data );
		Session::instance()->set_list_display_name( $key, $list_name );

		wp_send_json_success(
			array(
				'key'  => $key,
				'name' => $list_name,
				'data' => $data,
			)
		);
	}

	/**
	 * Delete a custom wishlist list (not the default list).
	 *
	 * @return void
	 */
	public function delete_wishlist(): void {
		$this->ensure_session();
		$this->ensure_feature_enabled();

		check_ajax_referer( $this->nonce_action, 'nonce' );

		if ( ! $this->check_rate_limit( 'delete_list' ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Too many requests. Please wait a moment.', 'skynet-smart-favorites' ),
				),
				429
			);
		}

		$settings = get_option( 'skynsmfa_settings', array() );
		if ( ! is_array( $settings ) ) {
			$settings = array();
		}
		if ( 'yes' !== ( $settings['skynsmfa_multiple_enable'] ?? 'yes' ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Multiple wishlists are disabled.', 'skynet-smart-favorites' ),
				)
			);
		}

		$wishlist_key = isset( $_POST['wishlist_key'] ) ? sanitize_text_field( wp_unslash( $_POST['wishlist_key'] ) ) : '';

		if ( '' === $wishlist_key || 'default' === $wishlist_key ) {
			wp_send_json_error(
				array(
					'message' => __( 'The default list cannot be deleted.', 'skynet-smart-favorites' ),
				)
			);
		}

		$data = Session::instance()->get_data();
		if ( ! isset( $data[ $wishlist_key ] ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Wishlist not found.', 'skynet-smart-favorites' ),
				)
			);
		}

		$data = Session::instance()->delete_list( $wishlist_key );

		wp_send_json_success(
			array(
				'owner' => Session::instance()->get_owner(),
				'data'  => $data,
			)
		);
	}

	/**
	 * Rename a wishlist list (default list keeps its key; custom lists may be re-keyed).
	 *
	 * @return void
	 */
	public function rename_wishlist(): void {
		$this->ensure_session();
		$this->ensure_feature_enabled();

		check_ajax_referer( $this->nonce_action, 'nonce' );

		if ( ! $this->check_rate_limit( 'rename_list' ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Too many requests. Please wait a moment.', 'skynet-smart-favorites' ),
				),
				429
			);
		}

		$wishlist_key = isset( $_POST['wishlist_key'] ) ? sanitize_text_field( wp_unslash( $_POST['wishlist_key'] ) ) : '';
		$list_name    = isset( $_POST['list_name'] ) ? sanitize_text_field( wp_unslash( $_POST['list_name'] ) ) : '';

		if ( '' === $wishlist_key ) {
			wp_send_json_error(
				array(
					'message' => __( 'Invalid wishlist.', 'skynet-smart-favorites' ),
				)
			);
		}

		if ( '' === $list_name ) {
			wp_send_json_error(
				array(
					'message' => __( 'Please provide a wishlist name.', 'skynet-smart-favorites' ),
				)
			);
		}

		if ( Session::instance()->list_display_name_exists( $list_name, $wishlist_key ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'A list with this name already exists. Please choose a different name.', 'skynet-smart-favorites' ),
				)
			);
		}

		$settings = get_option( 'skynsmfa_settings', array() );
		if ( ! is_array( $settings ) ) {
			$settings = array();
		}

		if ( 'default' !== $wishlist_key && 'yes' !== ( $settings['skynsmfa_multiple_enable'] ?? 'yes' ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Multiple wishlists are disabled.', 'skynet-smart-favorites' ),
				)
			);
		}

		$result = Session::instance()->rename_list( $wishlist_key, $list_name );
		if ( null === $result ) {
			wp_send_json_error(
				array(
					'message' => __( 'Wishlist not found.', 'skynet-smart-favorites' ),
				)
			);
		}

		wp_send_json_success(
			array(
				'key'   => $result['key'],
				'name'  => $result['name'],
				'data'  => $result['data'],
				'names' => Session::instance()->get_list_display_names(),
			)
		);
	}

	/**
	 * Fetch wishlist data.
	 *
	 * @return void
	 */
	public function get_wishlist(): void {
		$this->ensure_session();
		$this->ensure_feature_enabled();

		check_ajax_referer( $this->nonce_action, 'nonce' );

		if ( ! $this->check_rate_limit( 'get' ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Too many requests. Please wait a moment.', 'skynet-smart-favorites' ),
				),
				429
			);
		}

		wp_send_json_success(
			array(
				'owner' => Session::instance()->get_owner(),
				'data'  => Session::instance()->get_data(),
				'names' => Session::instance()->get_list_display_names(),
			)
		);
	}

	/**
	 * Move a single item to cart.
	 *
	 * @return void
	 */
	public function move_to_cart(): void {
		$this->ensure_session();
		$this->ensure_feature_enabled();

		check_ajax_referer( $this->nonce_action, 'nonce' );

		if ( ! $this->check_rate_limit( 'cart' ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Too many requests. Please wait a moment.', 'skynet-smart-favorites' ),
				),
				429
			);
		}

		if ( ! function_exists( 'WC' ) || ! WC()->cart ) {
			wp_send_json_error( array( 'message' => __( 'Cart not available.', 'skynet-smart-favorites' ) ) );
		}

		$product_id   = isset( $_POST['product_id'] ) ? absint( wp_unslash( $_POST['product_id'] ) ) : 0;
		$wishlist_key = isset( $_POST['wishlist_key'] ) ? sanitize_text_field( wp_unslash( $_POST['wishlist_key'] ) ) : 'default';

		if ( $product_id <= 0 ) {
			wp_send_json_error( array( 'message' => __( 'Invalid product.', 'skynet-smart-favorites' ) ) );
		}

		$result = $this->add_wishlist_line_to_cart( $product_id, $wishlist_key );

		if ( $result['success'] ) {
			Session::instance()->remove_item( $product_id, $wishlist_key );
			wp_send_json_success( array( 'message' => $result['message'] ) );
		}

		wp_send_json_error( array( 'message' => $result['message'] ) );
	}

	/**
	 * Add a wishlist line to the cart with variation validation.
	 *
	 * @param int    $product_id   Parent product ID in session data.
	 * @param string $wishlist_key Wishlist key.
	 * @return array{success: bool, message: string}
	 */
	private function add_wishlist_line_to_cart( int $product_id, string $wishlist_key ): array {
		$variation_id = Session::instance()->get_variation_id_for_item( $product_id, $wishlist_key );
		$product      = wc_get_product( $product_id );

		if ( ! $product ) {
			return array(
				'success' => false,
				'message' => __( 'Product not found.', 'skynet-smart-favorites' ),
			);
		}

		if ( $product->is_type( 'variable' ) && $variation_id <= 0 ) {
			return array(
				'success' => false,
				'message' => __( 'Please open the product page and choose options (color, size, etc.), then add it to your wishlist again.', 'skynet-smart-favorites' ),
			);
		}

		if ( $variation_id > 0 ) {
			$variation = wc_get_product( $variation_id );
			if ( ! $variation || (int) $variation->get_parent_id() !== $product_id ) {
				return array(
					'success' => false,
					'message' => __( 'Saved product options are no longer valid. Remove this item and add it again from the product page.', 'skynet-smart-favorites' ),
				);
			}
			if ( ! $variation->is_purchasable() || ! $variation->is_in_stock() ) {
				return array(
					'success' => false,
					'message' => __( 'This variation is not available to purchase right now.', 'skynet-smart-favorites' ),
				);
			}
		} elseif ( ! $product->is_purchasable() || ! $product->is_in_stock() ) {
			return array(
				'success' => false,
				'message' => __( 'This product is not available to purchase right now.', 'skynet-smart-favorites' ),
			);
		}

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

		if ( $added ) {
			return array(
				'success' => true,
				'message' => __( 'Product moved to cart.', 'skynet-smart-favorites' ),
			);
		}

		$notice = $this->get_last_cart_error_message();

		return array(
			'success' => false,
			'message' => $notice ? $notice : __( 'Could not add to cart. Check product options and stock.', 'skynet-smart-favorites' ),
		);
	}

	/**
	 * Last WooCommerce cart error notice message, if any.
	 *
	 * @return string
	 */
	private function get_last_cart_error_message(): string {
		if ( ! function_exists( 'wc_get_notices' ) ) {
			return '';
		}

		$notices = wc_get_notices( 'error' );
		if ( ! is_array( $notices ) || empty( $notices ) ) {
			return '';
		}

		$last = end( $notices );
		if ( ! is_array( $last ) || empty( $last['notice'] ) ) {
			return '';
		}

		return wp_strip_all_tags( (string) $last['notice'] );
	}

	/**
	 * Move multiple items to cart.
	 *
	 * @return void
	 */
	public function move_multiple_to_cart(): void {
		$this->ensure_session();
		$this->ensure_feature_enabled();
		$this->ensure_pro_bulk_cart();

		check_ajax_referer( $this->nonce_action, 'nonce' );

		if ( ! $this->check_rate_limit( 'cart_bulk' ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Too many requests. Please wait a moment.', 'skynet-smart-favorites' ),
				),
				429
			);
		}

		if ( ! function_exists( 'WC' ) || ! WC()->cart ) {
			wp_send_json_error( array( 'message' => __( 'Cart not available.', 'skynet-smart-favorites' ) ) );
		}

		$product_ids  = isset( $_POST['product_ids'] ) && is_array( $_POST['product_ids'] ) ? array_map( 'absint', wp_unslash( $_POST['product_ids'] ) ) : array();
		$wishlist_key = isset( $_POST['wishlist_key'] ) ? sanitize_text_field( wp_unslash( $_POST['wishlist_key'] ) ) : 'default';

		if ( empty( $product_ids ) ) {
			wp_send_json_error( array( 'message' => __( 'No products selected.', 'skynet-smart-favorites' ) ) );
		}

		$added_count = 0;
		foreach ( $product_ids as $pid ) {
			if ( $pid <= 0 ) {
				continue;
			}
			$result = $this->add_wishlist_line_to_cart( $pid, $wishlist_key );
			if ( $result['success'] ) {
				Session::instance()->remove_item( $pid, $wishlist_key );
				++$added_count;
			}
		}

		if ( $added_count > 0 ) {
			wp_send_json_success(
				array(
					'message' => sprintf(
						/* translators: %d: number of products moved to cart */
						_n( '%d product moved to cart.', '%d products moved to cart.', $added_count, 'skynet-smart-favorites' ),
						$added_count
					),
				)
			);
		} else {
			wp_send_json_error( array( 'message' => __( 'Could not add products to cart.', 'skynet-smart-favorites' ) ) );
		}
	}

	/**
	 * Add every in-stock item from a wishlist to the cart.
	 *
	 * @return void
	 */
	public function add_all_to_cart(): void {
		$this->ensure_session();
		$this->ensure_feature_enabled();
		$this->ensure_pro_bulk_cart();

		check_ajax_referer( $this->nonce_action, 'nonce' );

		if ( ! $this->check_rate_limit( 'cart_all' ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Too many requests. Please wait a moment.', 'skynet-smart-favorites' ),
				),
				429
			);
		}

		if ( ! function_exists( 'WC' ) || ! WC()->cart ) {
			wp_send_json_error( array( 'message' => __( 'Cart not available.', 'skynet-smart-favorites' ) ) );
		}

		$wishlist_key = isset( $_POST['wishlist_key'] ) ? sanitize_text_field( wp_unslash( $_POST['wishlist_key'] ) ) : 'default';
		$data         = Session::instance()->get_data();

		if ( ! isset( $data[ $wishlist_key ] ) || ! is_array( $data[ $wishlist_key ] ) ) {
			wp_send_json_error( array( 'message' => __( 'Wishlist is empty.', 'skynet-smart-favorites' ) ) );
		}

		$added_count = 0;
		foreach ( array_keys( $data[ $wishlist_key ] ) as $pid ) {
			$pid = absint( $pid );
			if ( $pid <= 0 ) {
				continue;
			}
			$result = $this->add_wishlist_line_to_cart( $pid, $wishlist_key );
			if ( $result['success'] ) {
				Session::instance()->remove_item( $pid, $wishlist_key );
				++$added_count;
			}
		}

		if ( $added_count > 0 ) {
			wp_send_json_success(
				array(
					'message' => sprintf(
						/* translators: %d: number of products added to cart */
						_n( '%d product added to cart.', '%d products added to cart.', $added_count, 'skynet-smart-favorites' ),
						$added_count
					),
				)
			);
		} else {
			wp_send_json_error( array( 'message' => __( 'No products could be added to cart.', 'skynet-smart-favorites' ) ) );
		}
	}
}
