<?php

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

/**
 * Frontend class.
 *
 * Handles API calls made from the fronted by the Survey Widget
 * Also handles the preview route
 *
 * @since 1.0.0
 *
 * @package UserFeedback
 * @author  David Paternina
 */
class UserFeedback_Frontend
{

	// Helpful static variables
	static $USERFEEDBACK_SURVEY_COOKIE_PREFIX = 'userfeedback-survey-';

	public function __construct()
	{
		require_once USERFEEDBACK_PLUGIN_DIR . 'includes/lib/class-mobile-detect.php';

		add_action('template_redirect', array($this, 'enqueue_styles_and_scripts_for_surveys'), 20);
		add_action('rest_api_init', array($this, 'register_frontend_routes'));
		add_filter( 'userfeedback_detect_page_id', array( $this, 'userfeedback_detect_page_id' ) );
	}

	public function userfeedback_detect_page_id()
	{
		$page_id = get_queried_object_id();

		if ( empty( $page_id ) ) {
			if (
				function_exists( 'is_shop' ) &&
				is_shop() &&
				function_exists( 'wc_get_page_id' )
			) {
				$page_id = wc_get_page_id( 'shop' );
			}
		}

		return $page_id;
	}

	/**
	 * Register frontend REST routes
	 *
	 * @return void
	 */
	public function register_frontend_routes()
	{
		register_rest_route(
			'userfeedback/v1',
			'/surveys/(?P<id>\w+)/responses',
			array(
				'methods'             => 'POST',
				'callback'            => array($this, 'save_survey_response'),
				'permission_callback' => '__return_true',
			)
		);

		register_rest_route(
			'userfeedback/v1',
			'/surveys/(?P<id>\w+)/impression',
			array(
				'methods'             => 'POST',
				'callback'            => array($this, 'record_survey_impression'),
				'permission_callback' => '__return_true',
			)
		);
	}

	/**
	 * Validate individual answer
	 *
	 * @param $value
	 * @param $question
	 * @return array
	 */
	private function validate_individual_answer($value, $question)
	{

		// Skip validation for empty values on non-required questions
		if (is_null($value) && !$question->settings->required) {
			return array(
				'is_valid' => true,
				'errors'   => array(),
			);
		}

		if (is_array($value)) {

			// Check if question accepts array as value
			if ($question->type !== 'checkbox') {
				return array(
					'is_valid' => false,
					'errors'   => array(
						sprintf(
							// translators: %s is the question ID.
							__("Question [%s] can't take an array as value.", 'userfeedback-lite'),
							$question->id
						),
					),
				);
			}

			// Recursively check each value
			$errors   = array();
			$is_valid = true;
			foreach ($value as $inner_value) {
				$answer_validation = $this->validate_individual_answer($inner_value, $question);
				$is_valid          = $is_valid && $answer_validation['is_valid'];
				$errors            = array_merge($errors, $answer_validation['errors']);
			}

			return array(
				'is_valid' => $is_valid,
				'errors'   => $errors,
			);
		} else {
			$errors   = array();
			$is_valid = true;

			// Check if string has less than 400 characters
			if (strlen($value) > 400) {
				$is_valid = false;
				$errors[] = __('Value exceeds 400 characters.', 'userfeedback-lite');
			}

			// If question accepts multiple values, check if $value is a valid option
			$types_with_options = array('checkbox', 'radio-button');

			if (in_array($question->type, $types_with_options)) {
				$available_options = $question->config->options;
				$value_is_allowed  = in_array($value, $available_options);

				$is_valid = $is_valid && $value_is_allowed;

				if (!$value_is_allowed) {
					$errors[] = sprintf(
						// translators: %s is the value that was submitted.
						__('Value "%s" is not allowed', 'userfeedback-lite'),
						$value
					);
				}
			} elseif ($question->type === 'email') {
				// Validate email
				$filtered_email = sanitize_email($value);

				if (empty($filtered_email)) {
					$is_valid = false;
					$errors[] = sprintf(
						__('The provided email is not valid', 'userfeedback-lite'),
						$value
					);
				}
			}

			// Validations for star-rating and nps are included in the question-types addon

			return apply_filters(
				'userfeedback_answer_validation',
				array(
					'is_valid' => $is_valid,
					'errors'   => $errors,
				),
				$value,
				$question
			);
		}
	}

	/**
	 * Validate Response answers
	 *
	 * @param $answers
	 * @param $survey_id
	 * @return array
	 */
	private function validate_response_answers($answers, $survey_id)
	{
		$errors  = array();
		$success = true;

		$survey = UserFeedback_Survey::find($survey_id);

		// Check if Survey exists
		if (!$survey) {
			return array(
				'success' => false,
				'errors'  => array(
					sprintf(
						// translators: %s is the survey ID.
						__('Survey with id %s does not exist.', 'userfeedback-lite'),
						$survey_id
					),
				),
				'status'  => 404,
			);
		}

		// Basic validation
		foreach ($answers as $answer) {
			$question_id = $answer['question_id'];
			$value       = $answer['value'];

			$question          = UserFeedback_Survey::search_question($survey, $question_id);
			$answer_validation = $this->validate_individual_answer($value, $question);

			$success = $success && $answer_validation['is_valid'];

			if (!$answer_validation['is_valid']) {
				$errors[] = array(
					'question_id' => $question_id,
					'errors'      => $answer_validation['errors'],
				);
			}
		}

		return array(
			'success' => $success,
			'errors'  => $errors,
		);
	}

	/**
	 * Save Survey response
	 *
	 * @param WP_REST_Request $request
	 * @return WP_REST_Response
	 */
	public function save_survey_response(WP_REST_Request $request)
	{
		if (!wp_verify_nonce($request->get_param('nonce'), "userfeedback_survey_submission-{$request['id']}")) {
			return new WP_REST_Response(null, 403);
		}

		$survey_id = $request['id'];

		$survey = (new UserFeedback_Survey())->find($survey_id);

		if('publish' !== $survey->status){
			return new WP_REST_Response(
				array(
					'success' => false,
					'errors'  => array(
						__('Survey is not available at the moment.', 'userfeedback-lite'),
					),
				),
				400
			);
		}

		$id_address = UserFeedback_Device_Detect::ip();

		$os      = UserFeedback_Device_Detect::os();
		$browser = UserFeedback_Device_Detect::browser();

		$device = UserFeedback_Device_Detect::deviceType();

		// Validate Answers
		$validation = $this->validate_response_answers($request->get_json_params()['answers'], $survey_id);

		if (!$validation['success']) {
			$status = isset($validation['status']) ? $validation['status'] : 400;
			return new WP_REST_Response(
				array(
					'success' => false,
					'errors'  => $validation['errors'],
				),
				$status
			);
		}

		// Sanitize requests answers
		$request_params = $request->get_json_params();

		if ( ! empty( $request_params['answers'] ) ) {
			foreach( $request_params['answers'] as $index => $answer ) {
				// Sanitize answer's value.
				$value = null;
				if ( is_string( $answer['value'] ) ) {
					$value = sanitize_text_field( $answer['value'] );
				} elseif ( is_numeric( $answer['value'] ) ) {
					$value = intval( $answer['value'] );
				}
				elseif (
					is_array( $answer['value'] )
					&& ! empty( $answer['value'] )
				) {
					$value = array_map( 'sanitize_text_field', $answer['value'] );
				}
				$request_params['answers'][ $index ]['value'] = $value;

				// Sanitize answer's extras.
				if ( ! empty( $answer['extra'] ) ) {
					foreach ( $answer['extra'] as $key => $extra ) {
						$extra = sanitize_text_field( $extra );
						$request_params['answers'][ $index ]['extra'][ $key ] = $extra;
					}
				}

			}
		}

		if ( ! empty( $request_params['page_submitted'] ) ) {
			if ( ! empty( $request_params['page_submitted']['id'] ) ) {
				$request_params['page_submitted']['id'] = intval( $request_params['page_submitted']['id'] );
			}
			if ( ! empty( $request_params['page_submitted']['name'] ) ) {
				$request_params['page_submitted']['name'] = sanitize_text_field( $request_params['page_submitted']['name'] );
			}
		}

		$response_id = UserFeedback_Response::create(
			array_merge(
				$request_params,
				array(
					'survey_id'    => sanitize_text_field($survey_id),
					'user_ip'      => $id_address,
					'user_browser' => $browser,
					'user_os'      => $os,
					'user_device'  => $device,
				)
			)
		);

		do_action('userfeedback_survey_response', $survey_id, $response_id, $request->get_json_params());

		return new WP_REST_Response(
			array(
				'success'     => true,
				'response_id' => $response_id,
			)
		);
	}

	/**
	 * Record Survey impression
	 *
	 * @param WP_REST_Request $request
	 * @return WP_REST_Response
	 */
	public function record_survey_impression(WP_REST_Request $request)
	{
		if (!wp_verify_nonce($request->get_param('nonce'), "userfeedback_survey_impression-{$request['id']}")) {
			return new WP_REST_Response(null, 403);
		}

		$survey_id = $request['id'];
		UserFeedback_Survey::record_impression($survey_id);

		return new WP_REST_Response(null, 204);
	}

	/**
	 * Load frontend styles
	 *
	 * @return void
	 */
	public function enqueue_styles_and_scripts_for_surveys()
	{
		global $post;

		if (empty($post)) {
			return;
		}

		$user_is_admin = current_user_can('administrator');
		$show_surveys_to_admin = apply_filters('userfeedback_enable_surveys_for_admins', false);

		// If admin is excluded from surveys, show the exclusion banner instead
		if ($user_is_admin && !$show_surveys_to_admin) {
			$this->render_exclusion_banner('administrator');
			return;
		}

		$surveys = $this->get_surveys_for_current_page();

		$surveys = array_map(
			function ($survey) {
				$survey->nonces = array(
					'submission' => wp_create_nonce("userfeedback_survey_submission-{$survey->id}"),
					'impression' => wp_create_nonce("userfeedback_survey_impression-{$survey->id}"),
				);
				return $survey;
			},
			$surveys
		);

		// For icon-choice question type, we need to extract the svg markup and send to frontend to render
		foreach($surveys as &$survey) {
			foreach($survey->questions as $question) {
				if ($question->type === 'icon-choice') {
					foreach($question->config->options as $option) {
						$svg_file_path = plugin_dir_path(USERFEEDBACK_PLUGIN_FILE) . 'assets/vue/icon-choices/svgs/' . $option->icon->style . '/' . $option->icon->icon . '.svg';

						if (file_exists($svg_file_path)) {
							$svg_content = file_get_contents($svg_file_path);
							$option->icon = $svg_content;
						}
					}
				}
			}
		}

		$this->register_chunc_scripts();
		/*
		 * If there are no Surveys available, we don't enqueue the scripts
		 */
		if (sizeof($surveys) > 0 || has_shortcode($post->post_content, UserFeedback_Shortcodes::$USERFEEDBACK_SURVEY_SHORTCODE)) {
			$this->enqueue_frontend_styles();
			$this->enqueue_base_frontend_scripts();
			$this->enqueue_frontend_scripts_for_surveys($surveys);
		}
	}

	/**
	 * Process individual rules with logic handling like the JavaScript function.
	 *
	 * @param array $rules Array of rules to process (AND or OR rules).
	 * @return array Array of booleans for each rule.
	 */
	private function process_rules($rules) {
		$result = [];

		global $post, $current_user;

		$user_roles = $current_user->roles;

		foreach ($rules as $rule) {
			$logic = $rule->logic;

			if (empty($rule->data)) {
				continue;
			}

			$value = isset($rule->data->id) ? $rule->data->id : $rule->data;

			// Remove trailing slashes from input value
			if (is_string($value)) {
				$value = preg_replace('/\/+$/', '', $value);
			}

			switch ($logic) {
				case 'user_logged_in': {
					$user_logged_in = is_user_logged_in();

					if ($value === 'user_logged_in') {
						$result[] = $user_logged_in;
					} elseif ($value === 'user_logged_out') {
						$result[] = !$user_logged_in;
					}
					break;
				}

				case 'page_type': {
					$page_type = userfeedback_get_type_of_page();

					$result[] = isset($page_type) && $value === $page_type;
					break;
				}

				case 'page_or_post_is': {
					$post_id = (is_singular()) ? $post->ID : false;

					$result[] = isset($post_id) && $value === $post_id;
					break;
				}

				case 'page_or_post_is_not': {
					$post_id = (is_singular()) ? $post->ID : false;

					$result[] = isset($post_id) && $value !== $post_id;
					break;
				}

				case 'post_type_is': {
					$post_type = (is_singular()) ? get_post_type() : false;

					$result[] = isset($post_type) && $value === $post_type;
					break;
				}

				case 'post_type_is_not': {
					$post_type = (is_singular()) ? get_post_type() : false;

					$result[] = isset($post_type) && $value !== $post_type;
					break;
				}

				case 'taxonomy_is': {
					$taxonomy = userfeedback_get_taxonomy();

					$result[] = isset($taxonomy) && $value === $taxonomy;
					break;
				}

				case 'taxonomy_is_not': {
					$taxonomy = userfeedback_get_taxonomy();

					$result[] = isset($taxonomy) && $value !== $taxonomy;
					break;
				}

				case 'taxonomy_term_is': {
					$taxonomy_term_ids = userfeedback_get_current_post_terms();

					$result[] = isset( $value ) && is_array( $taxonomy_term_ids ) && in_array( $value, $taxonomy_term_ids, true );
					break;
				}

				case 'taxonomy_term_is_not': {
					$taxonomy_term_ids = userfeedback_get_current_post_terms();

					$result[] = isset( $value ) && is_array( $taxonomy_term_ids ) && ! in_array( $value, $taxonomy_term_ids, true );
					break;
				}

				case 'referrer': {
					$referrer = isset($_SERVER['HTTP_REFERER']) ? esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : false; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized

					$result[] = isset($referrer) && (strpos($referrer, $value) !== false || strpos($value, $referrer) !== false);
					break;
				}

				case 'page_url_is': {
					$current_url = userfeedback_get_current_url();

					$result[] = isset($current_url) && strpos($current_url, $value) !== false;
					break;
				}

				case 'page_url_is_not': {
					$current_url = userfeedback_get_current_url();

					$result[] = isset($current_url) && strpos($current_url, $value) === false;
					break;
				}

				case 'page_url_contains': {
					$current_url = userfeedback_get_current_url();

					$result[] = strpos($current_url, $value) !== false;
					break;
				}

				case 'page_url_not_contains': {
					$current_url = userfeedback_get_current_url();

					$result[] = strpos($current_url, $value) === false;
					break;
				}

				case 'user_role': {
					$result[] = in_array($value, $user_roles, true);
					break;
				}

				case 'cookie_exist': {
					$cookie_name = $value;
					$result[] = isset($_COOKIE[$cookie_name]);
					break;
				}

				case 'cookie_not_exist': {
					$cookie_name = $value;
					$result[] = !isset($_COOKIE[$cookie_name]);
					break;
				}

				case 'query_parameter_contains': {
					$query_param = $value;
					$result[] = isset($_GET[$query_param]) && !empty($_GET[$query_param]); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonces are not appropriate for frontend public GET params used for survey targeting.
					break;
				}

				case 'query_parameter_not_contains': {
					$query_param = $value;
					$result[] = !isset($_GET[$query_param]); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonces are not appropriate for frontend public GET params used for survey targeting.
					break;
				}

				case 'query_parameter_regex': {
					$pattern = $value;
					$found = false;
					foreach ($_GET as $param => $param_value) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonces are not appropriate for frontend public GET params used for survey targeting.
						if (preg_match($pattern, $param_value)) {
							$found = true;
							break;
						}
					}
					$result[] = $found;
					break;
				}

				default:
					// Handle unknown logic cases if needed
					break;
			}
		}


		return $result;
	}

	/**
	 * Main function to filter and return all matched surveys based on the rules.
	 *
	 * @param array $surveys Array of surveys.
	 * @return array Array of all matching surveys.
	 */
	private function filter_surveys_by_advanced_targeting($surveys) {
		$matchedSurveys = [];

		foreach ($surveys as $survey) {
			if (!isset($survey->settings) || !is_object($survey->settings)) {
				continue;
			}
			$settings = $survey->settings;

			if (!isset($settings->targeting) || !is_object($settings->targeting)) {
				continue;
			}
			$targeting = $settings->targeting;

			if (isset($targeting->pages) && $targeting->pages === 'all') {
				// This survey is for all pages
				$matchedSurveys[] = $survey;
				continue;
			}

			if (!isset($targeting->page_rules) || !is_array($targeting->page_rules)) {
				continue;
			}
			$rules = $targeting->page_rules;

			$andRules = [];
			$orRules = [];

			foreach ($rules as $index => $rule) {
				$nextRule = isset($rules[$index + 1]) ? $rules[$index + 1] : false;

				if (
					(
						empty($rule->operator) && $nextRule && isset($nextRule->operator) && $nextRule->operator === '||'
					)
					||
					(
						isset($rule->operator) && $rule->operator === '||'
					)
				) {
					$orRules[] = $rule;
				} else {
					$andRules[] = $rule;
				}
			}

			// Process AND rules
			$processAndRules = $this->process_rules($andRules);
			$andRulesResult = empty($processAndRules) || !in_array(false, $processAndRules, true);

			// Process OR rules
			$processOrRules = $this->process_rules($orRules);
			$orRulesResult = empty($processOrRules) || in_array(true, $processOrRules, true);

			// Final result: add survey if it passes both AND and OR rule conditions
			if ($andRulesResult && $orRulesResult) {
				$matchedSurveys[] = $survey;
			}
		}

		return $matchedSurveys;
	}

	/**
	 * Get Surveys available for the current page
	 *
	 * @return array
	 */
	public function get_surveys_for_current_page()
	{
		$surveys = UserFeedback_Survey::where(
			array(
				'status'     => 'publish',
				'publish_at' => null,
			)
		)->or_where(
			array(
				'status' => 'publish',
				array(
					'publish_at',
					'<',
					current_time('mysql', true),
				),
			)
		)->select(array('title', 'questions', 'settings', 'type'))
			->sort('id', 'desc')
			->get();

		$surveys = $this->filter_surveys_by_advanced_targeting(
			$this->filter_surveys_by_geo_restrictions( $surveys )
		);

		$surveys = array_map(
			function ($survey) {
				$thank_you_config = $survey->settings->thank_you;

				if ($thank_you_config->type === 'redirect') {
					$page_id = $thank_you_config->redirect_to->id;

					if ('publish' == get_post_status($page_id)) {
						$thank_you_config->redirect_url = get_permalink($page_id);
					}
				} else if ($thank_you_config->type === 'conditional_redirect' && is_array($thank_you_config->conditions)) {
					foreach ($thank_you_config->conditions as &$condition) {
						if (isset($condition->page->id)) {
							$page_id = $condition->page->id;

							if ('publish' == get_post_status($page_id)) {
								$condition->redirect_url = get_permalink($page_id);
							}
						}
					}
				}

				$survey->cookie_name = self::get_survey_cookie_name($survey);
				return $survey;
			},
			$surveys
		);

		return $surveys;
	}

	/**
	 * Filters an array of survey objects based on their geographic restrictions.
	 *
	 * This function iterates through each survey in the provided array and checks if it has
	 * geo-targeting settings. If geo-targeting is enabled and set to 'select' specific
	 * countries, it extracts the country codes and applies a filter hook
	 * 'userfeedback_survey_show_in_country' to determine if the survey should be shown
	 * based on the user's location (determined by the hook). Surveys without valid
	 * geo-targeting settings are always included in the returned array.
	 * 
	 * @since 1.6.0
	 *
	 * @param array $surveys An array of survey objects. Each survey object is expected
	 * to potentially have a 'settings' property which is an object,
	 * and that 'settings' object may have a 'geo_targeting' property
	 * (also an object) containing targeting information.
	 *
	 * @return array An array containing only the surveys that should be displayed based
	 * on their geo-targeting restrictions (or those without restrictions).
	 */
	public function filter_surveys_by_geo_restrictions( $surveys ) {
		if ( ! is_array( $surveys ) ) {
			return $surveys;
		}

		return array_filter( $surveys, function ( $survey ) {
			$should_match = true;
	
			if (
				! isset( $survey->settings ) ||
				! is_object( $survey->settings ) ||
				! isset( $survey->settings->geo_targeting ) ||
				! is_object( $survey->settings->geo_targeting )
			) {
				return $should_match;
			}
	
			$geo_targeting = $survey->settings->geo_targeting;
	
			if (
				isset( $geo_targeting->target ) &&
				$geo_targeting->target === 'select' &&
				is_array( $geo_targeting->countries )
			) {
				$country_codes = array_map(
					function( $country ) {
						return strtolower( $country->value );
					},
					array_filter( $geo_targeting->countries, function( $country ) {
						return (
							is_object( $country ) &&
							isset( $country->value ) &&
							! empty( $country->value )
						);
					} )
				);

				$should_match = apply_filters(
					'userfeedback_survey_show_in_country',
					true,
					array(
						'target_countries' => $country_codes
					)
				);
			}
	
			return $should_match;
		} );
	}

	/**
	 * Get frontend asset full URL
	 *
	 * @since 1.0.0
	 * @param $path
	 * @return mixed|void
	 */
	public static function get_frontend_asset_url($path)
	{
		return esc_url(
			apply_filters(
				'userfeedback_frontend_assets_url',
				plugins_url($path, USERFEEDBACK_PLUGIN_FILE),
				$path
			)
		);
	}

	/**
	 * Enqueue frontend styles
	 *
	 * @return void
	 */
	public function enqueue_frontend_styles()
	{
		// Enqueue with super low priority so these load after theme CSS files
		add_action(
			'wp_head',
			function () {
				wp_enqueue_style(
					'userfeedback-frontend-styles',
					$this->get_frontend_asset_url('/assets/vue/css/frontend.css'),
					array(),
					userfeedback_get_asset_version()
				);
				$userfeedback_settings = userfeedback_get_options();
				// load custom fonts for the widget
				if(isset($userfeedback_settings['widget_font']['family']) && $userfeedback_settings['widget_font']['family'] !== ''){
					$font_family = str_replace(' ', '+', $userfeedback_settings['widget_font']['family']);
					$font_weight = (isset($userfeedback_settings['widget_font']['weight']) && $userfeedback_settings['widget_font']['weight'] !== '') ? $userfeedback_settings['widget_font']['weight'] : 'regular';
					$font_url = '';
					if($font_weight === 'regular'){
						$font_url = "https://fonts.googleapis.com/css?family={$font_family}&display=swap";
					}else {
						$font_url = "https://fonts.googleapis.com/css?family={$font_family}:{$font_weight}&display=swap";
					}
					wp_enqueue_style(
						'userfeedback-frontend-fonts',
						$font_url,
						array(),
						userfeedback_get_asset_version()
					);
					echo '<style>.userfeedback-widget * { font-family: \'' . esc_attr( $userfeedback_settings['widget_font']['family'] ) . '\' !important; }</style>';
				}

			},
			20
		);
	}

	private function register_chunc_scripts() {
		wp_register_script(
			'userfeedback-frontend-vendors',
			$this->get_frontend_asset_url('/assets/vue/js/chunk-vendors.js'),
			array(),
			userfeedback_get_asset_version(),
			true
		);

		wp_register_script(
			'userfeedback-frontend-common',
			$this->get_frontend_asset_url('/assets/vue/js/chunk-common.js'),
			array(),
			userfeedback_get_asset_version(),
			true
		);

		wp_localize_script(
			'userfeedback-frontend-common',
			'userfeedback_addons_frontend',
			array()
		);

		add_filter( 'script_loader_tag', function ( $tag, $handle ) {
			if (
				in_array(
					$handle,
					array(
						'userfeedback-frontend-vendors',
						'userfeedback-frontend-common'
					),
					true
				)
			) {
				return str_replace( ' src', ' defer src', $tag );
			}

			return $tag;
		}, 10, 2 );
	}

	/**
	 * Load frontend scripts
	 *
	 * @return void
	 */
	public function enqueue_base_frontend_scripts()
	{
		wp_register_script(
			'userfeedback-frontend-widget',
			$this->get_frontend_asset_url('/assets/vue/js/frontend.js'),
			apply_filters('userfeedback_frontend_script_dependencies', array( 'userfeedback-frontend-vendors', 'userfeedback-frontend-common' )),
			userfeedback_get_asset_version(),
			true
		);

		// This adds `defer` attribute to js files
		add_filter( 'script_loader_tag', function ( $tag, $handle ) {
			if (
				in_array(
					$handle,
					array(
						'userfeedback-frontend-widget'
					),
					true
				)
			) {
				return str_replace( ' src', ' defer src', $tag );
			}

			return $tag;
		}, 10, 2 );
	}

	/**
	 * Enqueue and localize script for preview
	 *
	 * @param $survey
	 * @return void
	 */
	public function enqueue_frontend_scripts_for_preview($survey)
	{
		wp_enqueue_script('userfeedback-frontend-widget');

		$localization_object = apply_filters(
			'userfeedback_frontend_script_localization',
			array(
				'wp_rest_nonce'      => wp_create_nonce('wp_rest'),
				'rest_url'           => rest_url(),
				'assets'             => plugins_url('/assets/vue', USERFEEDBACK_PLUGIN_FILE),
				'is_pro'             => userfeedback_is_pro_version(),
				'is_licensed'        => userfeedback_is_licensed(),
				'use_survey'         => $survey,
				'addons'             => array(),
				'widget_settings'    => userfeedback_get_frontend_widget_settings(),
			)
		);

		wp_localize_script(
			'userfeedback-frontend-widget',
			'userfeedback_frontend',
			$localization_object
		);
	}

	/**
	 * Enqueue Frontend scripts
	 *
	 * @return void
	 */
	public function enqueue_frontend_scripts_for_surveys($surveys)
	{
		global $post, $current_user;

		if (!is_admin() && $post) {
			$user_roles = [];
			if (is_user_logged_in()) {
				$user_roles = $current_user->roles;
			}
			wp_enqueue_script('userfeedback-frontend-widget');

			$localization_object = apply_filters(
				'userfeedback_frontend_script_localization',
				array(
					'wp_rest_nonce'   => wp_create_nonce('wp_rest'),
					'rest_url'        => rest_url(),
					'assets'          => plugins_url('/assets/vue', USERFEEDBACK_PLUGIN_FILE),
					'is_pro'          => userfeedback_is_pro_version(),
					'is_licensed'     => userfeedback_is_licensed(),
					'surveys'         => $surveys,
					'widget_settings' => userfeedback_get_frontend_widget_settings(),
					'is_preview'      => false,
					'integrations'    => array(),
					'addons'          => get_option('userfeedback_parsed_addons'),
					'current_page'    => array(
						'id'   => $post->ID,
						'name' => $post->post_title,
					),
					'disable_all_surveys' => userfeedback_disable_all_surveys(),
					'show_specific_survey' => userfeedback_show_specific_survey(),
					'is_singular' => is_singular(),
					'is_clarity_active' => function_exists( 'clarity_on_activation' ),
				)
			);

			wp_localize_script(
				'userfeedback-frontend-widget',
				'userfeedback_frontend',
				$localization_object
			);
		}
	}

	/**
	 * Get cookie name for survey
	 *
	 * @param $survey
	 * @return string
	 */
	public static function get_survey_cookie_name($survey)
	{
		return self::$USERFEEDBACK_SURVEY_COOKIE_PREFIX . $survey->id;
	}

	/**
	 * Render exclusion banner for logged-in users who are excluded from seeing surveys
	 *
	 * @since 1.x.x
	 * @param string $exclusion_reason Reason for exclusion (e.g., 'administrator', 'role')
	 * @return void
	 */
	private function render_exclusion_banner($exclusion_reason = 'administrator')
	{
		// Get banner configuration with filter for customization
		$config = apply_filters('userfeedback_exclusion_banner_config', array(
			'title'          => __('Survey is Hidden for Administrators', 'userfeedback'),
			'message'        => __('Surveys are hidden for administrator accounts to keep your survey results accurate. To see surveys on your site, use an incognito window or log out.', 'userfeedback')
		), $exclusion_reason);

		// Enqueue banner assets
		$this->enqueue_banner_assets($config);
	}

	/**
	 * Enqueue banner CSS and JS assets
	 *
	 * @since 1.x.x
	 * @param array $config Banner configuration
	 * @return void
	 */
	private function enqueue_banner_assets($config)
	{
		wp_enqueue_style(
			'userfeedback-admin-banner',
			plugins_url('/assets/css/admin-exclusion-banner.css', USERFEEDBACK_PLUGIN_FILE),
			array(),
			userfeedback_get_asset_version()
		);

		wp_enqueue_script(
			'userfeedback-admin-banner',
			plugins_url('/assets/js/admin-exclusion-banner.js', USERFEEDBACK_PLUGIN_FILE),
			array(),
			userfeedback_get_asset_version(),
			true
		);

		// Localize banner config for JS
		wp_localize_script(
			'userfeedback-admin-banner',
			'userfeedback_banner_config',
			$config
		);

		// Add banner HTML to footer
		add_action('wp_footer', array($this, 'render_banner_html'), 999);
	}

	/**
	 * Render banner HTML in footer
	 *
	 * @since 1.x.x
	 * @return void
	 */
	public function render_banner_html()
	{
		$logo_url = plugins_url('/assets/vue/img/user-feedback-logo.svg', USERFEEDBACK_PLUGIN_FILE);
		?>
		<div id="userfeedback-admin-banner" class="userfeedback-admin-banner" style="display:none;">
			<div class="userfeedback-admin-banner__card">
				<button class="userfeedback-admin-banner__close" type="button" aria-label="<?php esc_attr_e('Close', 'userfeedback'); ?>">
					<svg width="12" height="12" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
						<path d="M14 1.41L12.59 0L7 5.59L1.41 0L0 1.41L5.59 7L0 12.59L1.41 14L7 8.41L12.59 14L14 12.59L8.41 7L14 1.41Z" fill="currentColor"/>
					</svg>
				</button>
				<div class="userfeedback-admin-banner__media">
					<div class="userfeedback-admin-banner__logo">
						<img src="<?php echo esc_url($logo_url); ?>" alt="<?php esc_attr_e('UserFeedback', 'userfeedback'); ?>">
					</div>
					<div class="userfeedback-admin-banner__body">
						<h3 class="userfeedback-admin-banner__title"></h3>
						<p class="userfeedback-admin-banner__message"></p>
					</div>
				</div>
			</div>
		</div>
		<?php
	}
}

new UserFeedback_Frontend();
