<?php
/**
 * Gutenberg block for rendering UGC reviews.
 *
 * @package Ugcify\Blocks
 */

namespace Ugcify\Blocks;

use Ugcify\Helpers\FeatureGate;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class ReviewsBlock
 */
class ReviewsBlock {
	/**
	 * Frontend preview script handle.
	 *
	 * @var string
	 */
	private $preview_script_handle = 'ugcify-block-preview-script';

	/**
	 * Frontend preview style handle.
	 *
	 * @var string
	 */
	private $preview_style_handle = 'ugcify-block-preview-style';

	/**
	 * Constructor.
	 */
	public function __construct() {
		add_action( 'init', array( $this, 'register' ) );
		add_action( 'enqueue_block_assets', array( $this, 'enqueue_editor_preview_assets' ) );
		add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_editor_preview_assets' ) );
		add_filter( 'block_editor_settings_all', array( $this, 'inject_preview_styles_into_editor' ), 10, 2 );
	}

	/**
	 * Register block and editor assets.
	 *
	 * @return void
	 */
	public function register() {
		$script_handle = 'ugcify-block-reviews';
		$asset_file    = UGCIFY_PATH . 'assets/blocks/reviews.asset.php';
		$script_file   = UGCIFY_PATH . 'assets/blocks/reviews.js';

		if ( ! file_exists( $script_file ) ) {
			return;
		}

		$this->register_frontend_preview_assets();

		$asset_data = array(
			'dependencies' => array(
				'wp-api-fetch',
				'wp-block-editor',
				'wp-blocks',
				'wp-components',
				'wp-element',
				'wp-i18n',
				'wp-server-side-render',
			),
			'version'      => UGCIFY_VERSION,
		);

		if ( file_exists( $asset_file ) ) {
			$loaded_asset = require $asset_file;
			if ( is_array( $loaded_asset ) ) {
				$asset_data = array_merge( $asset_data, $loaded_asset );
			}
		}

		wp_register_script(
			$script_handle,
			UGCIFY_URL . 'assets/blocks/reviews.js',
			$asset_data['dependencies'],
			(string) filemtime( $script_file ),
			true
		);

		wp_set_script_translations( $script_handle, 'ugcify', UGCIFY_PATH . 'languages' );

		register_block_type(
			'ugcify/reviews',
			array(
				'api_version'     => 2,
				'editor_script'   => $script_handle,
				'style'           => $this->preview_style_handle,
				'editor_style'    => $this->preview_style_handle,
				'script'          => $this->preview_script_handle,
				'attributes'      => $this->get_block_attributes(),
				'render_callback' => array( $this, 'render' ),
			)
		);
	}

	/**
	 * Render block output.
	 *
	 * @param array $attributes Block attributes.
	 * @return string
	 */
	public function render( $attributes ) {
		do_action( 'ugcify_assets_needed' );

		if ( ! shortcode_exists( 'ugcify_reviews' ) ) {
			return '';
		}

		$product_id  = isset( $attributes['productId'] ) ? absint( $attributes['productId'] ) : 0;
		$categories  = $this->sanitize_slug_array( isset( $attributes['categories'] ) ? $attributes['categories'] : array() );
		$tags        = $this->sanitize_slug_array( isset( $attributes['tags'] ) ? $attributes['tags'] : array() );
		$instance_id = isset( $attributes['instanceId'] ) ? sanitize_html_class( (string) $attributes['instanceId'] ) : '';

		if ( '' === $instance_id ) {
			$instance_id = 'ugcify-block-' . substr( md5( wp_json_encode( $attributes ) ), 0, 10 );
		}

		$attributes = $this->normalize_attributes_for_plan( is_array( $attributes ) ? $attributes : array() );

		$shortcode_attributes = array(
			'instance_id' => $instance_id,
		);

		if ( $product_id > 0 ) {
			$shortcode_attributes['product_id'] = (string) $product_id;
		}

		if ( ! empty( $categories ) ) {
			$shortcode_attributes['categories'] = implode( ',', $categories );
		}

		if ( ! empty( $tags ) ) {
			$shortcode_attributes['tags'] = implode( ',', $tags );
		}

		$template_keys = array_keys( $this->get_block_attributes() );
		foreach ( $template_keys as $key ) {
			if ( in_array( $key, array( 'instanceId', 'productId', 'categories', 'tags' ), true ) ) {
				continue;
			}
			if ( ! array_key_exists( $key, $attributes ) ) {
				continue;
			}

			if ( is_bool( $attributes[ $key ] ) ) {
				$shortcode_attributes[ $key ] = $attributes[ $key ] ? '1' : '0';
			} else {
				$shortcode_attributes[ $key ] = (string) $attributes[ $key ];
			}
		}

		$shortcode = '[ugcify_reviews';
		foreach ( $shortcode_attributes as $key => $value ) {
			$shortcode .= sprintf( ' %1$s="%2$s"', sanitize_key( $key ), esc_attr( $value ) );
		}
		$shortcode .= ']';

		return do_shortcode( $shortcode );
	}

	/**
	 * Register frontend asset handles for block preview/runtime.
	 *
	 * @return void
	 */
	private function register_frontend_preview_assets() {
		$script_handle = $this->preview_script_handle;
		$style_handle  = $this->preview_style_handle;
		$script_src    = UGCIFY_URL . 'assets/frontend/app.js';
		$style_src     = UGCIFY_URL . 'assets/frontend/styles.css';
		$script_file   = UGCIFY_PATH . 'assets/frontend/app.js';
		$style_file    = UGCIFY_PATH . 'assets/frontend/styles.css';

		if ( file_exists( $script_file ) && ! wp_script_is( $script_handle, 'registered' ) ) {
			$script_asset_file = UGCIFY_PATH . 'assets/frontend/app.asset.php';
			$script_asset      = array(
				'dependencies' => array( 'jquery' ),
				'version'      => (string) filemtime( $script_file ),
			);

			if ( file_exists( $script_asset_file ) ) {
				$loaded_asset = require $script_asset_file;
				if ( is_array( $loaded_asset ) ) {
					$script_asset = array_merge( $script_asset, $loaded_asset );
				}
			}

			wp_register_script(
				$script_handle,
				$script_src,
				$script_asset['dependencies'],
				$script_asset['version'],
				true
			);
		}

		if ( file_exists( $style_file ) && ! wp_style_is( $style_handle, 'registered' ) ) {
			$style_asset_file = UGCIFY_PATH . 'assets/frontend/styles.asset.php';
			$style_asset      = array(
				'dependencies' => array(),
				'version'      => (string) filemtime( $style_file ),
			);

			if ( file_exists( $style_asset_file ) ) {
				$loaded_asset = require $style_asset_file;
				if ( is_array( $loaded_asset ) ) {
					$style_asset = array_merge( $style_asset, $loaded_asset );
				}
			}
			$style_asset['version'] = (string) filemtime( $style_file );

			wp_register_style( $style_handle, $style_src, $style_asset['dependencies'], $style_asset['version'] );
		}
	}

	/**
	 * Enqueue assets and localization for block editor preview.
	 *
	 * @return void
	 */
	public function enqueue_editor_preview_assets() {
		if ( ! is_admin() ) {
			return;
		}

		$this->register_frontend_preview_assets();

		if ( wp_style_is( $this->preview_style_handle, 'registered' ) ) {
			wp_enqueue_style( $this->preview_style_handle );

			$style_file = UGCIFY_PATH . 'assets/frontend/styles.css';
			if ( file_exists( $style_file ) && is_readable( $style_file ) ) {
				$style_contents = file_get_contents( $style_file );
				if ( is_string( $style_contents ) && '' !== trim( $style_contents ) ) {
					wp_add_inline_style( $this->preview_style_handle, $style_contents );
				}
			}
		}

		if ( wp_script_is( $this->preview_script_handle, 'registered' ) ) {
			wp_enqueue_script( $this->preview_script_handle );
			wp_set_script_translations( $this->preview_script_handle, 'ugcify', UGCIFY_PATH . 'languages' );

			$feature_keys = array(
				'block_studio_advanced',
				'block_studio_reels',
				'block_studio_gallery',
			);
			$enabled_features = array();
			foreach ( $feature_keys as $key ) {
				$enabled_features[ $key ] = FeatureGate::is_enabled( $key );
			}

			wp_localize_script(
				$this->preview_script_handle,
				'ugcCommerce',
				array(
					'apiUrl'       => rest_url( 'ugcify/v1' ),
					'nonce'        => wp_create_nonce( 'wp_rest' ),
					'pluginUrl'    => UGCIFY_URL,
					'productId'    => 0,
					'perPage'      => apply_filters( 'ugcify_reviews_per_page', 3 ),
					'locale'       => str_replace( '_', '-', get_locale() ),
					'isProActive'  => (bool) apply_filters( 'ugcify_is_pro_active', false ),
					'licensePlan'  => (string) apply_filters( 'ugcify_license_plan', '' ),
					'features'     => $enabled_features,
					'upgradeUrl'   => esc_url( apply_filters( 'ugcify_upgrade_url', admin_url( 'admin.php?page=ugcify#/license' ) ) ),
					'i18n'         => array(
						'guest'                => __( 'Guest', 'ugcify' ),
						'reviewMediaAlt'       => __( 'Review Media', 'ugcify' ),
						'errorLoadingReview'   => __( 'Error loading review. Please try again.', 'ugcify' ),
						'failedFetchReview'    => __( 'Failed to fetch review', 'ugcify' ),
						'failedFetchReviewIds' => __( 'Failed to fetch review ids', 'ugcify' ),
						'addingToCart'         => __( 'Adding...', 'ugcify' ),
						'addedToCart'          => __( 'Added', 'ugcify' ),
						'addToCartError'       => __( 'Try Again', 'ugcify' ),
						'readMore'             => __( 'Read More', 'ugcify' ),
						'readLess'             => __( 'Read less', 'ugcify' ),
					),
				)
			);
		}
	}

	/**
	 * Inject preview CSS into block editor canvas settings.
	 *
	 * @param array $settings Existing block editor settings.
	 * @param mixed $context  Block editor context.
	 * @return array
	 */
	public function inject_preview_styles_into_editor( $settings, $context ) {
		if ( ! is_admin() || ! is_array( $settings ) ) {
			return $settings;
		}

		$style_file = UGCIFY_PATH . 'assets/frontend/styles.css';
		if ( ! file_exists( $style_file ) || ! is_readable( $style_file ) ) {
			return $settings;
		}

		$css = file_get_contents( $style_file );
		if ( ! is_string( $css ) || '' === trim( $css ) ) {
			return $settings;
		}

		if ( ! isset( $settings['styles'] ) || ! is_array( $settings['styles'] ) ) {
			$settings['styles'] = array();
		}

		$settings['styles'][] = array( 'css' => $css );

		return $settings;
	}

	/**
	 * Block attributes definition.
	 *
	 * @return array<string,array<string,mixed>>
	 */
	private function get_block_attributes() {
		return array(
			'instanceId'            => array( 'type' => 'string', 'default' => '' ),
			'productId'             => array( 'type' => 'number', 'default' => 0 ),
			'categories'            => array( 'type' => 'array', 'items' => array( 'type' => 'string' ), 'default' => array() ),
			'tags'                  => array( 'type' => 'array', 'items' => array( 'type' => 'string' ), 'default' => array() ),
			'widgetType'            => array( 'type' => 'string', 'default' => 'grid' ),
			'mediaMosaicStyle'      => array( 'type' => 'string', 'default' => 'grid' ),
			'showHeaderTitle'       => array( 'type' => 'boolean', 'default' => true ),
			'title'                 => array( 'type' => 'string', 'default' => 'Customers are saying' ),
			'titleFontWeight'       => array( 'type' => 'string', 'default' => '600' ),
			'titleFontSize'         => array( 'type' => 'string', 'default' => 'medium' ),
			'emptyReviewText'       => array( 'type' => 'string', 'default' => 'No customer review yet. Be the first to review!' ),
			'primaryColor'          => array( 'type' => 'string', 'default' => '#201CFE' ),
			'titleColor'            => array( 'type' => 'string', 'default' => '#000000' ),
			'bodyFontColor'         => array( 'type' => 'string', 'default' => '#444444' ),
			'cardBgColor'           => array( 'type' => 'string', 'default' => '#FFFFFF' ),
			'ratingColor'           => array( 'type' => 'string', 'default' => '#FFA800' ),
			'buttonTextColor'       => array( 'type' => 'string', 'default' => '#FFFFFF' ),
			'filterFillColor'       => array( 'type' => 'string', 'default' => '#FFFFFF' ),
			'filterStrokeColor'     => array( 'type' => 'string', 'default' => '#201CFE' ),
			'filterIconColor'       => array( 'type' => 'string', 'default' => '#292D32' ),
			'readMoreColor'         => array( 'type' => 'string', 'default' => '#000000' ),
			'loadMoreTextColor'     => array( 'type' => 'string', 'default' => '#201CFE' ),
			'loadMoreBgColor'       => array( 'type' => 'string', 'default' => '#FFFFFF' ),
			'loadMoreBorderColor'   => array( 'type' => 'string', 'default' => '#201CFE' ),
			'reviewerNameFormat'    => array( 'type' => 'string', 'default' => 'full' ),
			'reviewerNameFontSize'  => array( 'type' => 'string', 'default' => 'medium' ),
			'showCustomerAvatar'    => array( 'type' => 'boolean', 'default' => true ),
			'showVerifiedCheck'     => array( 'type' => 'boolean', 'default' => true ),
			'showInfluencerBadge'   => array( 'type' => 'boolean', 'default' => true ),
			'reviewDateFormat'      => array( 'type' => 'string', 'default' => 'd M, Y' ),
			'starRatingSize'        => array( 'type' => 'string', 'default' => 'medium' ),
			'reviewTextSize'        => array( 'type' => 'string', 'default' => 'medium' ),
			'reviewTextLength'      => array( 'type' => 'string', 'default' => 'large' ),
			'reviewCardBorderRadius' => array( 'type' => 'string', 'default' => '10' ),
			'testimonialQuoteSize'  => array( 'type' => 'string', 'default' => 'medium' ),
			'testimonialQuoteColor' => array( 'type' => 'string', 'default' => '#322EFE' ),
			'testimonialQuoteOpacity' => array( 'type' => 'string', 'default' => '1' ),
			'reviewColumn'          => array( 'type' => 'string', 'default' => '3' ),
			'reviewsPerPage'        => array( 'type' => 'string', 'default' => '3' ),
			'paginationType'        => array( 'type' => 'string', 'default' => 'page_number' ),
			'showReviews'           => array( 'type' => 'boolean', 'default' => true ),
			'showLoadMoreButton'    => array( 'type' => 'boolean', 'default' => true ),
			'loadMoreTextSize'      => array( 'type' => 'string', 'default' => 'medium' ),
			'loadMoreBorderRadius'  => array( 'type' => 'string', 'default' => '10' ),
			'customCSS'             => array( 'type' => 'string', 'default' => '' ),
			'blockTemplate'         => array( 'type' => 'string', 'default' => 'minimal_gallery' ),
			'gridStyle'             => array( 'type' => 'string', 'default' => 'masonry' ),
			'columnsDesktop'        => array( 'type' => 'number', 'default' => 4 ),
			'gapSpacing'            => array( 'type' => 'number', 'default' => 16 ),
			'lazyLoadImages'        => array( 'type' => 'boolean', 'default' => true ),
			'autoplayVideo'         => array( 'type' => 'boolean', 'default' => false ),
			'enableLightbox'        => array( 'type' => 'boolean', 'default' => true ),
			'showMediaCarousel'     => array( 'type' => 'boolean', 'default' => true ),
			'mediaCarouselItemsToShow' => array( 'type' => 'string', 'default' => '10' ),
			'tagStyle'              => array( 'type' => 'string', 'default' => 'pulsing_dot' ),
			'directAddToCart'       => array( 'type' => 'boolean', 'default' => true ),
			'enableUpvotes'         => array( 'type' => 'boolean', 'default' => false ),
			'socialShareButtons'    => array( 'type' => 'boolean', 'default' => false ),
			'customersAlsoBought'   => array( 'type' => 'boolean', 'default' => false ),
			'showStories'           => array( 'type' => 'boolean', 'default' => true ),
			'storiesTitle'          => array( 'type' => 'string', 'default' => 'Customer Stories' ),
			'storiesMaxCount'       => array( 'type' => 'number', 'default' => 8 ),
			'showAddYours'          => array( 'type' => 'boolean', 'default' => true ),
			'showCommunity'         => array( 'type' => 'boolean', 'default' => true ),
			'communityTitle'        => array( 'type' => 'string', 'default' => 'Community Reviews' ),
			'communitySubtitle'     => array( 'type' => 'string', 'default' => 'See what our customers are saying' ),
			'showShareBtn'          => array( 'type' => 'boolean', 'default' => true ),
		);
	}

	/**
	 * Normalize template and premium-lockable settings.
	 *
	 * @param array $attributes Block attributes.
	 * @return array
	 */
	private function normalize_attributes_for_plan( $attributes ) {
		$defaults = array();
		foreach ( $this->get_block_attributes() as $key => $schema ) {
			$defaults[ $key ] = isset( $schema['default'] ) ? $schema['default'] : null;
		}

		$normalized = array_merge( $defaults, $attributes );

		$requested_template = isset( $normalized['blockTemplate'] ) ? sanitize_key( (string) $normalized['blockTemplate'] ) : 'minimal_gallery';
		$allowed_templates  = array( 'minimal_gallery', 'reels', 'carousel', 'card_carousel', 'media_mosaic', 'testimonial_carousel' );
		if ( ! in_array( $requested_template, $allowed_templates, true ) ) {
			$requested_template = 'minimal_gallery';
		}

		if ( 'reels' === $requested_template && ! FeatureGate::is_enabled( 'block_studio_reels' ) ) {
			$requested_template = 'minimal_gallery';
		}

		if ( in_array( $requested_template, array( 'carousel', 'card_carousel', 'media_mosaic', 'testimonial_carousel' ), true ) && ! FeatureGate::is_enabled( 'block_studio_gallery' ) ) {
			$requested_template = 'minimal_gallery';
		}

		$normalized['blockTemplate'] = $requested_template;

		if ( ! FeatureGate::is_enabled( 'block_studio_advanced' ) ) {
			$advanced_locked = array(
				'primaryColor',
				'titleColor',
				'bodyFontColor',
				'cardBgColor',
				'ratingColor',
				'buttonTextColor',
				'filterFillColor',
				'filterStrokeColor',
				'filterIconColor',
				'readMoreColor',
				'loadMoreTextColor',
				'loadMoreBgColor',
				'loadMoreBorderColor',
				'lazyLoadImages',
				'autoplayVideo',
				'enableLightbox',
				'customCSS',
			);
			foreach ( $advanced_locked as $field ) {
				$normalized[ $field ] = $defaults[ $field ];
			}
		}

		$disabled_fields = array( 'enableUpvotes', 'socialShareButtons', 'customersAlsoBought' );
		foreach ( $disabled_fields as $field ) {
			$normalized[ $field ] = $defaults[ $field ];
		}

		if ( 'reels' === $requested_template ) {
			$normalized['widgetType'] = 'reels';
		} elseif ( 'carousel' === $requested_template ) {
			$normalized['widgetType'] = 'gallery';
		} elseif ( in_array( $requested_template, array( 'card_carousel', 'media_mosaic', 'testimonial_carousel' ), true ) ) {
			$normalized['widgetType'] = $requested_template;
		} else {
			$widget_type = isset( $normalized['widgetType'] ) ? sanitize_key( (string) $normalized['widgetType'] ) : 'grid';
			$normalized['widgetType'] = in_array( $widget_type, array( 'grid', 'masonry', 'slider' ), true ) ? $widget_type : 'grid';
		}

		return $normalized;
	}

	/**
	 * Sanitize a list of term slugs.
	 *
	 * @param mixed $raw_slugs Raw slugs.
	 * @return array
	 */
	private function sanitize_slug_array( $raw_slugs ) {
		if ( ! is_array( $raw_slugs ) ) {
			return array();
		}

		$slugs = array_map( 'sanitize_title', $raw_slugs );
		$slugs = array_filter( $slugs );
		$slugs = array_values( array_unique( $slugs ) );

		return $slugs;
	}
}
