<?php

namespace Cart\notify\WooCommerce;

defined( 'ABSPATH' ) || exit;

/**
 * WooCommerce cart event bridge for non-AJAX add-to-cart flows.
 */
class CartEvents {
	/**
	 * WooCommerce session key used to carry fallback notification payload.
	 */
	const SESSION_KEY = 'cart_notify_pending_notification';

	/**
	 * Register cart hooks.
	 */
	public function __construct() {
		add_action( 'woocommerce_add_to_cart', array( $this, 'capture_non_ajax_add_to_cart' ), 10, 6 );
	}

	/**
	 * Capture successful non-AJAX add-to-cart details for next-page notification.
	 *
	 * @param string $cart_item_key Cart item key.
	 * @param int    $product_id Product ID.
	 * @param int    $quantity Added quantity.
	 * @param int    $variation_id Variation product ID.
	 * @param array  $variation Variation attributes.
	 * @param array  $cart_item_data Cart item data.
	 * @return void
	 */
	public function capture_non_ajax_add_to_cart( $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data ) {
		unset( $cart_item_key, $cart_item_data );

		if ( ! $this->is_frontend_non_ajax_request() ) {
			return;
		}

		$session = $this->get_session();
		if ( ! $session ) {
			return;
		}

		$payload = $this->build_notification_payload( $product_id, $quantity, $variation_id, $variation );
		if ( empty( $payload ) ) {
			return;
		}

		$session->set( self::SESSION_KEY, $payload );
	}

	/**
	 * Read and clear pending fallback notification payload from WooCommerce session.
	 *
	 * @return array
	 */
	public function consume_pending_notification() {
		$session = $this->get_session();
		if ( ! $session ) {
			return array();
		}

		$payload = $session->get( self::SESSION_KEY, array() );
		if ( method_exists( $session, '__unset' ) ) {
			$session->__unset( self::SESSION_KEY );
		} else {
			$session->set( self::SESSION_KEY, null );
		}

		if ( ! is_array( $payload ) || empty( $payload ) ) {
			return array();
		}

		return $this->sanitize_payload( $payload );
	}

	/**
	 * Check whether the current request is frontend and non-AJAX.
	 *
	 * @return bool
	 */
	private function is_frontend_non_ajax_request() {
		if ( is_admin() ) {
			return false;
		}

		if ( function_exists( 'wp_doing_ajax' ) && wp_doing_ajax() ) {
			return false;
		}

		if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
			return false;
		}

		return true;
	}

	/**
	 * Get active WooCommerce session handler when available.
	 *
	 * @return \WC_Session|null
	 */
	private function get_session() {
		if ( ! function_exists( 'WC' ) ) {
			return null;
		}

		$woocommerce = WC();
		if ( ! $woocommerce || empty( $woocommerce->session ) ) {
			return null;
		}

		return $woocommerce->session;
	}

	/**
	 * Build a fallback notification payload.
	 *
	 * @param int   $product_id Product ID.
	 * @param int   $quantity Added quantity.
	 * @param int   $variation_id Variation product ID.
	 * @param array $variation Variation attributes.
	 * @return array
	 */
	private function build_notification_payload( $product_id, $quantity, $variation_id, $variation ) {
		$product = $this->resolve_product( $product_id, $variation_id );
		if ( ! $product ) {
			return array();
		}

		if ( method_exists( $product, 'is_type' ) && $product->is_type( 'external' ) ) {
			return array();
		}

		$title = '';
		if ( method_exists( $product, 'get_name' ) ) {
			$title = $product->get_name();
		}

		$fallback_product = null;
		if ( '' === $title && $product_id > 0 && function_exists( 'wc_get_product' ) ) {
			$fallback_product = wc_get_product( $product_id );
			if ( $fallback_product && method_exists( $fallback_product, 'get_name' ) ) {
				$title = $fallback_product->get_name();
			}
		}

		$quantity_value = is_numeric( $quantity ) ? (float) $quantity : 1.0;
		if ( $quantity_value <= 0 ) {
			$quantity_value = 1.0;
		}

		return array(
			'title'             => $title,
			'image'             => $this->get_product_image_url( $product, $fallback_product ),
			'quantity'          => $quantity_value,
			'variation_summary' => $this->get_variation_summary( $variation, $product ),
			'cart_count'        => $this->get_cart_count(),
			'cart_subtotal'     => $this->get_cart_subtotal_text(),
			'product_id'        => absint( $product_id ),
			'variation_id'      => absint( $variation_id ),
		);
	}

	/**
	 * Resolve the best product object for notification data.
	 *
	 * @param int $product_id Product ID.
	 * @param int $variation_id Variation ID.
	 * @return \WC_Product|false
	 */
	private function resolve_product( $product_id, $variation_id ) {
		if ( ! function_exists( 'wc_get_product' ) ) {
			return false;
		}

		if ( $variation_id > 0 ) {
			$variation_product = wc_get_product( $variation_id );
			if ( $variation_product ) {
				return $variation_product;
			}
		}

		return wc_get_product( $product_id );
	}

	/**
	 * Resolve product image URL.
	 *
	 * @param \WC_Product      $product Product object.
	 * @param \WC_Product|null $fallback_product Fallback product object.
	 * @return string
	 */
	private function get_product_image_url( $product, $fallback_product = null ) {
		$image_id = 0;

		if ( $product && method_exists( $product, 'get_image_id' ) ) {
			$image_id = absint( $product->get_image_id() );
		}

		if ( ! $image_id && $product && method_exists( $product, 'get_parent_id' ) ) {
			$parent_id = absint( $product->get_parent_id() );
			if ( $parent_id > 0 && function_exists( 'wc_get_product' ) ) {
				$parent_product = wc_get_product( $parent_id );
				if ( $parent_product && method_exists( $parent_product, 'get_image_id' ) ) {
					$image_id = absint( $parent_product->get_image_id() );
				}
			}
		}

		if ( ! $image_id && $fallback_product && method_exists( $fallback_product, 'get_image_id' ) ) {
			$image_id = absint( $fallback_product->get_image_id() );
		}

		if ( $image_id <= 0 || ! function_exists( 'wp_get_attachment_image_url' ) ) {
			return '';
		}

		$image = wp_get_attachment_image_url( $image_id, 'woocommerce_thumbnail' );
		return is_string( $image ) ? $image : '';
	}

	/**
	 * Build variation summary text from variation attributes.
	 *
	 * @param array       $variation Variation attributes.
	 * @param \WC_Product $product Product object.
	 * @return string
	 */
	private function get_variation_summary( $variation, $product ) {
		if ( empty( $variation ) || ! is_array( $variation ) ) {
			return '';
		}

		$parts = array();
		foreach ( $variation as $attribute_name => $attribute_value ) {
			$raw_name  = is_string( $attribute_name ) ? $attribute_name : '';
			$raw_value = is_scalar( $attribute_value ) ? (string) $attribute_value : '';

			if ( '' === $raw_name || '' === $raw_value ) {
				continue;
			}

			$label = $this->normalize_attribute_name( $raw_name, $product );
			$value = $this->normalize_attribute_value( $raw_value );
			if ( '' === $label || '' === $value ) {
				continue;
			}

			$parts[] = $label . ': ' . $value;
		}

		return implode( ', ', $parts );
	}

	/**
	 * Normalize variation attribute label for display.
	 *
	 * @param string      $attribute_name Raw attribute name.
	 * @param \WC_Product $product Product object.
	 * @return string
	 */
	private function normalize_attribute_name( $attribute_name, $product ) {
		$name = preg_replace( '/^attribute_/', '', $attribute_name );
		$name = is_string( $name ) ? $name : '';

		if ( function_exists( 'wc_attribute_label' ) ) {
			$name = wc_attribute_label( $name, $product );
		}

		$name = str_replace( array( 'pa_', '_', '-' ), array( '', ' ', ' ' ), (string) $name );
		return trim( ucfirst( sanitize_text_field( $name ) ) );
	}

	/**
	 * Normalize variation attribute value for display.
	 *
	 * @param string $value Raw attribute value.
	 * @return string
	 */
	private function normalize_attribute_value( $value ) {
		$normalized = wc_clean( $value );
		$normalized = str_replace( array( '_', '-' ), ' ', (string) $normalized );
		return trim( $normalized );
	}

	/**
	 * Sanitize stored session payload before exposing it to JS.
	 *
	 * @param array $payload Raw payload.
	 * @return array
	 */
	private function sanitize_payload( $payload ) {
		$quantity = 0.0;
		if ( isset( $payload['quantity'] ) && is_numeric( $payload['quantity'] ) ) {
			$quantity = (float) $payload['quantity'];
		}
		if ( $quantity <= 0 ) {
			$quantity = 0.0;
		}

		return array(
			'title'             => isset( $payload['title'] ) ? sanitize_text_field( (string) $payload['title'] ) : '',
			'image'             => isset( $payload['image'] ) ? esc_url_raw( (string) $payload['image'] ) : '',
			'quantity'          => $quantity,
			'variation_summary' => isset( $payload['variation_summary'] ) ? sanitize_text_field( (string) $payload['variation_summary'] ) : '',
			'cart_count'        => isset( $payload['cart_count'] ) ? absint( $payload['cart_count'] ) : 0,
			'cart_subtotal'     => isset( $payload['cart_subtotal'] ) ? sanitize_text_field( (string) $payload['cart_subtotal'] ) : '',
			'product_id'        => isset( $payload['product_id'] ) ? absint( $payload['product_id'] ) : 0,
			'variation_id'      => isset( $payload['variation_id'] ) ? absint( $payload['variation_id'] ) : 0,
		);
	}

	/**
	 * Get current cart item count.
	 *
	 * @return int
	 */
	private function get_cart_count() {
		if ( ! function_exists( 'WC' ) || ! WC() || empty( WC()->cart ) || ! method_exists( WC()->cart, 'get_cart_contents_count' ) ) {
			return 0;
		}

		return absint( WC()->cart->get_cart_contents_count() );
	}

	/**
	 * Get current cart subtotal text.
	 *
	 * @return string
	 */
	private function get_cart_subtotal_text() {
		if ( ! function_exists( 'WC' ) || ! WC() || empty( WC()->cart ) || ! method_exists( WC()->cart, 'get_cart_subtotal' ) ) {
			return '';
		}

		$subtotal = WC()->cart->get_cart_subtotal();
		return sanitize_text_field( wp_strip_all_tags( (string) $subtotal ) );
	}
}
