<?php
/**
 * Review Summarizer — pulls WooCommerce product reviews, sends them
 * to the active text provider, stores a short testimonial-style summary,
 * and optionally renders it on the product page.
 *
 * @package CatalogPilot\AiStudio
 */

namespace CatalogPilot\AiStudio;

defined( 'ABSPATH' ) || exit;

final class Review {

	const META_KEY      = '_cpais_review_summary';
	const META_META_KEY = '_cpais_review_summary_meta'; // sentiment, count, generated_at

	private static $instance = null;

	public static function instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Per-request guard so the auto-display block renders at most once per page
	 * even if multiple compatible hooks fire (classic themes vs block themes).
	 */
	private $auto_rendered = array();

	private function __construct() {
		add_shortcode( 'cpais_review_summary', array( $this, 'render_shortcode' ) );

		// Always register hooks; each callback checks the setting at request
		// time so toggles take effect without a plugin reload.

		// Classic WooCommerce themes — fires under the product summary block.
		add_action( 'woocommerce_single_product_summary', array( $this, 'render_auto' ), 25 );

		// Block themes (e.g. TwentyTwentyFive) — append after the WC product
		// summary block render or after the post-content block.
		add_filter( 'render_block', array( $this, 'maybe_inject_after_block' ), 10, 2 );
	}

	/**
	 * Fetch up to N approved reviews for a product. Returns plain-text snippets.
	 *
	 * @param int $product_id
	 * @param int $limit
	 * @return array{count: int, samples: string[], avg_rating: float}
	 */
	public static function fetch_reviews( $product_id, $limit = 50 ) {
		$product_id = absint( $product_id );
		if ( ! $product_id ) {
			return array( 'count' => 0, 'samples' => array(), 'avg_rating' => 0.0 );
		}

		$comments = get_comments(
			array(
				'post_id'  => $product_id,
				'type'     => 'review',
				'status'   => 'approve',
				'number'   => max( 1, min( 200, (int) $limit ) ),
				'orderby'  => 'comment_date_gmt',
				'order'    => 'DESC',
			)
		);

		$samples    = array();
		$rating_sum = 0;
		$rating_n   = 0;
		foreach ( $comments as $c ) {
			$content = wp_strip_all_tags( $c->comment_content );
			if ( '' === $content ) {
				continue;
			}
			$rating = (int) get_comment_meta( $c->comment_ID, 'rating', true );
			if ( $rating > 0 ) {
				$rating_sum += $rating;
				$rating_n++;
			}
			// Truncate per-review to 280 chars to keep prompt size reasonable.
			$samples[] = mb_substr( $content, 0, 280 );
		}

		return array(
			'count'      => count( $samples ),
			'samples'    => $samples,
			'avg_rating' => $rating_n > 0 ? round( $rating_sum / $rating_n, 1 ) : 0.0,
		);
	}

	public static function save( $product_id, $summary, array $meta = array() ) {
		$product_id = absint( $product_id );
		if ( ! $product_id || 'product' !== get_post_type( $product_id ) ) {
			return false;
		}
		$summary = sanitize_text_field( (string) $summary );
		if ( '' === $summary ) {
			delete_post_meta( $product_id, self::META_KEY );
			delete_post_meta( $product_id, self::META_META_KEY );
			return 0;
		}
		update_post_meta( $product_id, self::META_KEY, $summary );

		$meta_clean = array(
			'count'        => isset( $meta['count'] )        ? absint( $meta['count'] )           : 0,
			'avg_rating'   => isset( $meta['avg_rating'] )   ? (float) $meta['avg_rating']        : 0.0,
			'sentiment'    => isset( $meta['sentiment'] )    ? sanitize_key( $meta['sentiment'] ) : '',
			'generated_at' => time(),
		);
		update_post_meta( $product_id, self::META_META_KEY, $meta_clean );
		return strlen( $summary );
	}

	public static function get( $product_id ) {
		$summary = get_post_meta( absint( $product_id ), self::META_KEY, true );
		$meta    = get_post_meta( absint( $product_id ), self::META_META_KEY, true );
		return array(
			'summary' => is_string( $summary ) ? $summary : '',
			'meta'    => is_array( $meta ) ? $meta : array(),
		);
	}

	public function render_shortcode( $atts ) {
		$atts = shortcode_atts( array( 'id' => 0 ), $atts, 'cpais_review_summary' );
		$pid  = absint( $atts['id'] );
		if ( ! $pid && function_exists( 'is_product' ) && is_product() ) {
			$pid = (int) get_queried_object_id();
		}
		if ( ! $pid ) {
			return '';
		}
		$data = self::get( $pid );
		if ( '' === $data['summary'] ) {
			return '';
		}

		$count = ! empty( $data['meta']['count'] ) ? (int) $data['meta']['count'] : 0;
		$intro = $count > 0
			? sprintf(
				/* translators: 1: review count */
				_n( 'Based on %d review:', 'Based on %d reviews:', $count, 'catalogpilot-ai-studio-for-woocommerce' ),
				$count
			)
			: __( 'Customer summary:', 'catalogpilot-ai-studio-for-woocommerce' );

		return sprintf(
			'<div class="cpais-review-summary"><strong class="cpais-review-summary__intro">%s</strong> <span class="cpais-review-summary__text">%s</span></div>',
			esc_html( $intro ),
			esc_html( $data['summary'] )
		);
	}

	public function render_auto() {
		$html = $this->maybe_get_auto_html();
		if ( '' !== $html ) {
			echo wp_kses_post( $html );
		}
	}

	/**
	 * Append the review summary right after the WooCommerce product-summary
	 * block (or the post-content block as a fallback) on block themes.
	 */
	public function maybe_inject_after_block( $block_content, $block ) {
		$name = isset( $block['blockName'] ) ? (string) $block['blockName'] : '';
		if ( 'woocommerce/product-summary' !== $name && 'core/post-content' !== $name ) {
			return $block_content;
		}
		$html = $this->maybe_get_auto_html();
		if ( '' === $html ) {
			return $block_content;
		}
		return $block_content . $html;
	}

	/**
	 * Returns the auto-display HTML once per request (guarded by product id),
	 * or '' if disabled / not on a product page / no summary saved.
	 */
	private function maybe_get_auto_html() {
		if ( ! function_exists( 'is_product' ) || ! is_product() ) {
			return '';
		}
		$settings = Settings::get_all();
		if ( empty( $settings['review_summary_display'] ) ) {
			return '';
		}
		$product_id = (int) get_queried_object_id();
		if ( ! $product_id || isset( $this->auto_rendered[ $product_id ] ) ) {
			return '';
		}
		$html = $this->render_shortcode( array() );
		if ( '' === $html ) {
			return '';
		}
		$this->auto_rendered[ $product_id ] = true;
		return $html;
	}
}
