<?php

/**
 * Plugin Name:       Proofwp - Visual Product Reviews for WooCommerce
 * Plugin URI:        https://proofwp.com/
 * Description:       Sell more with unlimited product reviews, UGC, ratings, trust badges, and testimonials. Proofwp lets you showcase image and video reviews in WooCommerce to boost trust and conversions instantly.
 * Version:           1.3.12
 * Requires at least: 5.8
 * Requires PHP:      7.4
 * Author:            Debuggers Studio
 * Author URI:        https://debuggersstudio.com/
 * License:           GPL v2 or later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       proofwp
 * Domain Path:       /languages
 */

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

require_once plugin_dir_path(__FILE__) . 'includes/helpers.php';
require_once plugin_dir_path(__FILE__) . 'includes/class-db.php';
require_once plugin_dir_path(__FILE__) . 'includes/api/DSProofwp_Router.php';
require_once plugin_dir_path(__FILE__) . 'includes/block/class-block.php';
require_once plugin_dir_path(__FILE__) . 'includes/services/DSProofwp_Review_Request_Service.php';
require_once plugin_dir_path(__FILE__) . 'includes/services/DSProofwp_Review_Request_Hooks.php';
require_once plugin_dir_path(__FILE__) . 'includes/services/DSProofwp_Product_Page_Review.php';
require_once plugin_dir_path(__FILE__) . 'includes/domain/repositories/Review_Request_Repository.php';
require_once plugin_dir_path(__FILE__) . 'includes/class-feedback.php';

final class DSProofwp_Plugin
{
	private const VERSION = '1.3.12';
	private const VITE_CLIENT_HANDLE = 'dsproofwp-vite-client';
	private const SCRIPT_HANDLE = 'dsproofwp-app';
	private const STYLE_HANDLE  = 'dsproofwp-app';
	private const ADMIN_STYLE_HANDLE = 'dsproofwp-admin';
	private const MENU_SLUG     = 'dsproofwp';
	private const ALL_REVIEWS_MENU_SLUG = 'dsproofwp-all-reviews';
	private const LICENSE_MENU_SLUG = 'dsproofwp-license';
	private const TOOLS_MENU_SLUG = 'dsproofwp-tools';
	private const SETTINGS_MENU_SLUG = 'dsproofwp-settings';
	private const REVIEW_REMINDER_MENU_SLUG = 'dsproofwp-review-reminder';
	private const REVIEW_FEED_FORM_MENU_SLUG = 'dsproofwp-review-feed-form';
	private const DEV_SERVER_URL = 'http://localhost:1818';
	private const PRO_PLUGIN_BASENAME = 'proofwp-pro/proofwp-pro.php';

	/** @var string[] */
	private static array $page_hooks = [];
	/** @var array|null */
	private static ?array $detected_target_widgets = null;
	private static bool $has_rendered_frontend_config = false;
	private static bool $shortcode_rendered = false;

	public static function init(): void
	{
		if (version_compare(get_option('dsproofwp_new_schema_version', '1.0.0'), '1.4.0', '<')) {
			DSProofwp_DB::create_or_update_tables();
		}

		add_action('init',                   [self::class, 'register_shortcode']);
		add_action('init',                   [self::class, 'register_review_landing_routing']);
		add_action('plugins_loaded',         [self::class, 'maybe_boot_elementor']);
		add_action('admin_menu',             [self::class, 'register_admin_menu']);
		add_action('admin_enqueue_scripts',  [self::class, 'manage_script']);
		add_action('wp_enqueue_scripts',     [self::class, 'register_frontend_assets']);
		add_action('admin_head',             [self::class, 'maybe_render_react_preamble']);
		add_action('wp_head',                [self::class, 'print_frontend_config'], 1);
		add_action('wp_head',                [self::class, 'maybe_render_frontend_react_preamble']);
		add_action('wp_footer',              [self::class, 'print_frontend_config'], 1);
		add_action('template_redirect',      [self::class, 'handle_review_landing_page']);
		add_filter('script_loader_tag',      [self::class, 'maybe_mark_script_as_module'], 10, 3); //Fallback
		add_filter('query_vars',             [self::class, 'register_review_query_vars']);

		DSProofwp_Router::init();

		self::init_review_reminder();
		DSProofwp_Product_Page_Review::init();
	}

	private static function init_review_reminder(): void
	{
		global $wpdb;
		$repo = new DSProofwp_Review_Request_Repository($wpdb);
		$service = new DSProofwp_Review_Request_Service($repo);
		$hooks = new DSProofwp_Review_Request_Hooks($service);
		$hooks->register();
	}

	public static function maybe_boot_elementor(): void
	{
		if (! did_action('elementor/loaded')) {
			return;
		}

		require_once plugin_dir_path(__FILE__) . 'includes/elementor/class-elementor-init.php';
	}

	public static function register_shortcode(): void
	{
		add_shortcode('proofwp', [self::class, 'render_shortcode']);
	}

	public static function register_review_query_vars(array $vars): array
	{
		$vars[] = 'proofwp_review_token';
		return $vars;
	}

	public static function register_review_landing_routing(): void
	{
		add_rewrite_rule(
			'^proofwp-review/([a-zA-Z0-9]+)/?$',
			'index.php?proofwp_review_token=$matches[1]',
			'top'
		);
	}

	public static function handle_review_landing_page(): void
	{
		$token = get_query_var('proofwp_review_token', '');
		if (empty($token)) {
			return;
		}

		// Load the review landing page template and exit
		require_once plugin_dir_path(__FILE__) . 'templates/one-page-review.php';
		exit;
	}

	public static function register_admin_menu(): void
	{
		$top_level_hook = add_menu_page(
			__('Proofwp', 'proofwp'),
			__('Proofwp', 'proofwp'),
			'manage_options',
			self::MENU_SLUG,
			[self::class, 'render_admin_page'],
			plugins_url('public/proofwp.svg', __FILE__),
			56
		);

		// The submenu that mirrors the top-level page
		$submenu_hook = add_submenu_page(
			self::MENU_SLUG,
			__('All Widget', 'proofwp'),
			__('All Widget', 'proofwp'),
			'manage_options',
			self::MENU_SLUG,
			[self::class, 'render_admin_page']
		);

		$manage_submenu_hook = add_submenu_page(
			self::MENU_SLUG,
			__('All Reviews', 'proofwp'),
			__('All Reviews', 'proofwp'),
			'manage_options',
			self::ALL_REVIEWS_MENU_SLUG,
			[self::class, 'render_admin_page']
		);

		$review_feed_form_submenu_hook = add_submenu_page(
			self::MENU_SLUG,
			__('Feed and Form', 'proofwp'),
			__('Feed and Form', 'proofwp'),
			'manage_options',
			self::REVIEW_FEED_FORM_MENU_SLUG,
			[self::class, 'render_admin_page']
		);

		$review_reminder_submenu_hook = add_submenu_page(
			self::MENU_SLUG,
			__('Review Reminder', 'proofwp'),
			__('Review Reminder', 'proofwp'),
			'manage_options',
			self::REVIEW_REMINDER_MENU_SLUG,
			[self::class, 'render_admin_page']
		);

		$import_submenu_hook = add_submenu_page(
			self::MENU_SLUG,
			__('Tools', 'proofwp'),
			__('Tools', 'proofwp'),
			'manage_options',
			self::TOOLS_MENU_SLUG,
			[self::class, 'render_admin_page']
		);



		// $settings_submenu_hook = add_submenu_page(
		// 	self::MENU_SLUG,
		// 	__('Settings', 'proofwp'),
		// 	__('Settings', 'proofwp'),
		// 	'manage_options',
		// 	self::SETTINGS_MENU_SLUG,
		// 	[self::class, 'render_admin_page']
		// );

		self::$page_hooks = array_filter([
			(string) $top_level_hook,
			(string) $submenu_hook,
			(string) $manage_submenu_hook,
			(string) $import_submenu_hook,
			(string) $review_reminder_submenu_hook,
			(string) $review_feed_form_submenu_hook,
			// (string) $settings_submenu_hook,
		]);
	}

	public static function manage_script(string $hook): void
	{
		if (! self::should_enqueue_own_assets()) {
			do_action('dsproofwp_enqueue_admin_assets', $hook);
			return;
		}

		self::enqueue_admin_styles();

		if (! in_array($hook, self::$page_hooks, true)) {
			return;
		}

		wp_enqueue_media();

		if (self::is_dev_environment()) {
			self::enqueue_admin_dev_assets();
		} else {
			self::enqueue_admin_prod_assets();
		}
	}

	/**
	 * admin_head fires on every admin page — guard it.
	 */
	public static function maybe_render_react_preamble(): void
	{
		if (! self::should_enqueue_own_assets()) {
			return;
		}

		$screen = get_current_screen();

		if (! $screen || ! in_array($screen->id, self::$page_hooks, true)) {
			return;
		}

		if (self::is_dev_environment()) {
			self::render_react_preamble();
		}
	}

	public static function maybe_render_frontend_react_preamble(): void
	{
		if (! self::should_enqueue_own_assets()) {
			return;
		}

		if (! self::$shortcode_rendered && ! is_singular() && ! (function_exists('is_account_page') && is_account_page())) {
			return;
		}

		if (self::is_dev_environment()) {
			self::render_react_preamble();
		}
	}

	private static function is_dev_environment(): bool
	{
		return file_exists(plugin_dir_path(__FILE__) . 'index.html');
	}

	private static function render_react_preamble(): void
	{
		wp_print_inline_script_tag(
			"import RefreshRuntime from '" . esc_url_raw(self::DEV_SERVER_URL . '/@react-refresh') . "';
			RefreshRuntime.injectIntoGlobalHook(window);
			window.\$RefreshReg\$ = () => {};
			window.\$RefreshSig\$ = () => (type) => type;
			window.__vite_plugin_react_preamble_installed__ = true;",
			[
				'type' => 'module',
			]
		);
	}

	public static function register_frontend_assets(): void
	{
		if (! self::should_enqueue_own_assets()) {
			return;
		}

		if (self::is_dev_environment()) {
			self::register_frontend_dev_assets();
		} else {
			self::register_frontend_prod_assets();
		}

		// Enqueue on product pages if reviews are enabled
		if (function_exists('is_product') && is_product() && 'yes' === get_option('woocommerce_enable_reviews')) {
			if (self::is_dev_environment()) {
				self::enqueue_frontend_dev_assets();
			} else {
				self::enqueue_frontend_prod_assets();
			}
		}

		// Enqueue on WooCommerce My Account pages for Write A Review modal
		if (function_exists('is_account_page') && is_account_page()) {
			if (self::is_dev_environment()) {
				self::enqueue_frontend_dev_assets();
			} else {
				self::enqueue_frontend_prod_assets();
			}
		}
	}

	private static function enqueue_admin_dev_assets(): void
	{
		self::enqueue_vite_client();

		if (function_exists('wp_enqueue_script_module')) {
			wp_enqueue_script_module(
				self::SCRIPT_HANDLE,
				self::DEV_SERVER_URL . '/src/main.tsx',
				[self::VITE_CLIENT_HANDLE],
				null // Don't cache-bust in dev; Vite handles it
			);

			return;
		}

		wp_enqueue_script(
			self::SCRIPT_HANDLE,
			self::DEV_SERVER_URL . '/src/main.tsx',
			[],
			null, // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion -- Dev server assets should not receive a WordPress version query string.
			true
		);
	}

	private static function enqueue_frontend_dev_assets(): void
	{
		wp_enqueue_script(self::VITE_CLIENT_HANDLE);
		wp_enqueue_script(self::SCRIPT_HANDLE);
	}

	private static function enqueue_vite_client(): void
	{
		if (function_exists('wp_enqueue_script_module')) {
			wp_enqueue_script_module(
				self::VITE_CLIENT_HANDLE,
				self::DEV_SERVER_URL . '/@vite/client',
				[],
				null
			);

			return;
		}

		wp_enqueue_script(
			self::VITE_CLIENT_HANDLE,
			self::DEV_SERVER_URL . '/@vite/client',
			[],
			null, // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion -- Dev server assets should not receive a WordPress version query string.
			true
		);
	}

	private static function register_frontend_dev_assets(): void
	{
		wp_register_script(
			self::VITE_CLIENT_HANDLE,
			self::DEV_SERVER_URL . '/@vite/client',
			[],
			null, // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion -- Dev server assets should not receive a WordPress version query string.
			true
		);

		wp_register_script(
			self::SCRIPT_HANDLE,
			self::DEV_SERVER_URL . '/src/main.tsx',
			[self::VITE_CLIENT_HANDLE],
			null, // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion -- Dev server assets should not receive a WordPress version query string.
			true
		);
	}

	private static function enqueue_admin_styles(): void
	{
		wp_enqueue_style(
			self::ADMIN_STYLE_HANDLE,
			plugins_url('assets/css/admin.css', __FILE__),
			[],
			self::VERSION
		);
	}

	private static function enqueue_admin_prod_assets(): void
	{
		$script_src     = plugins_url('dist/proofwp.min.js', __FILE__);

		if (function_exists('wp_enqueue_script_module')) {
			wp_enqueue_script_module(
				self::SCRIPT_HANDLE,
				$script_src,
				[],
				self::VERSION
			);
		} else {
			wp_enqueue_script(
				self::SCRIPT_HANDLE,
				$script_src,
				[],
				self::VERSION,
				true
			);
		}

		wp_enqueue_style(
			self::STYLE_HANDLE,
			plugins_url('dist/proofwp.min.css', __FILE__),
			[],
			self::VERSION
		);
	}

	private static function enqueue_frontend_prod_assets(): void
	{
		wp_enqueue_script(self::SCRIPT_HANDLE);
		wp_enqueue_style(self::STYLE_HANDLE);
	}

	private static function register_frontend_prod_assets(): void
	{
		$script_src  = plugins_url('dist/proofwp.min.js', __FILE__);
		$style_src   = plugins_url('dist/proofwp.min.css', __FILE__);


		wp_register_script(
			self::SCRIPT_HANDLE,
			$script_src,
			[],
			self::VERSION,
			true
		);

		wp_register_style(
			self::STYLE_HANDLE,
			$style_src,
			[],
			self::VERSION
		);
	}

	//Fallback module handler
	public static function maybe_mark_script_as_module(string $tag, string $handle, string $src): string
	{
		if (! self::should_enqueue_own_assets()) {
			return $tag;
		}

		$module_handles = [self::VITE_CLIENT_HANDLE, self::SCRIPT_HANDLE];

		if (! in_array($handle, $module_handles, true)) {
			return $tag;
		}

		return wp_get_script_tag(
			[
				'type' => 'module',
				'src'  => $src,
				'id'   => "{$handle}-js",
			]
		);
	}

	public static function render_admin_page(): void
	{
		$current_admin_page = isset($_GET['page'])
			? sanitize_key((string) wp_unslash($_GET['page']))
			: '';

		$dsproofwp_config  = [
			'assetBaseUrl'     => plugins_url('public/', __FILE__),
			'restApiBaseUrl'   => rest_url('dsproofwp/v1/'),
			'restNonce'        => wp_create_nonce('wp_rest'),
			'currentAdminPage' => $current_admin_page,
			'isProActive'      => self::is_pro_active(),
			'isLicenseActive'  => self::is_license_active(),
			'adminPageUrls'    => [
				'widgets'    => menu_page_url(self::MENU_SLUG, false),
				'allReviews' => menu_page_url(self::ALL_REVIEWS_MENU_SLUG, false),
				'license'    => menu_page_url(self::LICENSE_MENU_SLUG, false),
				'tools'      => menu_page_url(self::TOOLS_MENU_SLUG, false),
				'settings'   => menu_page_url(self::SETTINGS_MENU_SLUG, false),
				'reviewReminder' => menu_page_url(self::REVIEW_REMINDER_MENU_SLUG, false),
				'reviewFeedForm' => menu_page_url(self::REVIEW_FEED_FORM_MENU_SLUG, false),
			],
		];

		$dsproofwp_config = apply_filters('dsproofwp_admin_config', $dsproofwp_config);
?>
		<div class="wrap">
			<?php wp_print_inline_script_tag('window.dsproofwpConfig = ' . wp_json_encode($dsproofwp_config) . ';'); ?>
			<div id="dsproofwp-root"></div>
		</div>
<?php
	}

	public static function render_shortcode(array $atts = []): string
	{
		$atts = shortcode_atts(
			[
				'id' => 0,
				'wt' => '',
			],
			$atts,
			'proofwp'
		);

		$widget_id = absint($atts['id']);
		$widget_type = sanitize_key((string) $atts['wt']);

		if ($widget_id < 1) {
			return '<p>' . esc_html__('Invalid widget ID.', 'proofwp') . '</p>';
		}

		self::$shortcode_rendered = true;

		if (self::should_enqueue_own_assets()) {
			if (self::is_dev_environment()) {
				self::enqueue_frontend_dev_assets();
			} else {
				self::enqueue_frontend_prod_assets();
			}
		} else {
			do_action('dsproofwp_enqueue_frontend_assets');
			do_action('dsproofwp_shortcode_rendered');
		}

		$config_markup = self::maybe_render_frontend_config();

		return $config_markup . '<div class="dsproofwp-shortcode" id="dsproofwp-shortcode-' . esc_attr((string) $widget_id) . '" data-id="' . esc_attr((string) $widget_id) . '" data-widget-type="' . esc_attr($widget_type) . '"></div>';
	}

	public static function maybe_render_frontend_config(): string
	{
		if (self::$has_rendered_frontend_config) {
			return '';
		}

		self::$has_rendered_frontend_config = true;

		$current_user = wp_get_current_user();
		$is_logged_in = $current_user->exists();
		$has_reviewed = false;

		if ($is_logged_in && function_exists('is_product') && is_product()) {
			$product_id = (int) get_the_ID();
			if ($product_id > 0) {
				global $wpdb;
				$repo = new DSProofwp_Review_Repository($wpdb);
				$has_reviewed = $repo->has_user_reviewed($product_id, (int) $current_user->ID, (string) $current_user->user_email);
			}
		}

		$dsproofwp_config  = [
			'assetBaseUrl'   => plugins_url('public/', __FILE__),
			'restApiBaseUrl' => rest_url('dsproofwp/v1/'),
			'restNonce'      => wp_create_nonce('wp_rest'),
			'isProActive'    => self::is_pro_active(),
			'isLicenseActive' => self::is_license_active(),
			'currentUser'    => [
				'isLoggedIn'  => $is_logged_in,
				'name'        => $is_logged_in ? ($current_user->display_name ?: $current_user->user_login) : '',
				'email'       => $is_logged_in ? $current_user->user_email : '',
				'hasReviewed' => $has_reviewed,
			],
		];

		$config_js = 'window.dsproofwpConfig = ' . wp_json_encode($dsproofwp_config) . ';';

		return wp_get_inline_script_tag($config_js);
	}

	public static function print_frontend_config(): void
	{
		if (is_admin()) {
			return;
		}

		$config_tag = self::maybe_render_frontend_config();
		if (!empty($config_tag)) {
			echo $config_tag;
		}
	}

	private static function should_enqueue_own_assets(): bool
	{
		return (bool) apply_filters('dsproofwp_should_enqueue_assets', true);
	}

	public static function is_pro_active(): bool
	{
		if (class_exists('DSProofwp_Pro_Plugin') && method_exists('DSProofwp_Pro_Plugin', 'is_plugin_active')) {
			return (bool) DSProofwp_Pro_Plugin::is_plugin_active();
		}

		if (class_exists('DSProofwp_Pro_Plugin')) {
			return true;
		}

		if (! function_exists('is_plugin_active')) {
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
		}

		return is_plugin_active(self::PRO_PLUGIN_BASENAME);
	}

	public static function is_license_active(): bool
	{
		if (class_exists('DSProofwp_Pro_Plugin') && method_exists('DSProofwp_Pro_Plugin', 'is_license_active')) {
			return (bool) DSProofwp_Pro_Plugin::is_license_active();
		}

		return false;
	}
}

register_activation_hook(__FILE__, ['DSProofwp_DB', 'activate']);
register_activation_hook(__FILE__, function () {
	flush_rewrite_rules();
});

DSProofwp_Plugin::init();
