<?php
/**
 * Renders the cookie banner config and enqueues its assets.
 *
 * @package BlaminhorEssentials
 */

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

/**
 * Decides whether to show the banner, what to inject in the page, and
 * enqueues the runtime JS/CSS. Designed to be 100% cache-friendly: the
 * page HTML is identical for every visitor, and the banner runtime
 * fetches the per-visitor context (geo, lang, gpc) via a REST call.
 */
class Blaminhor_Essentials_Cookies_Banner_Renderer {

	/**
	 * @var Blaminhor_Essentials_Cookies_Consent_Manager
	 */
	protected $consent;

	/**
	 * @var array Settings of the cookies module.
	 */
	protected $settings;

	/**
	 * @var string Module URL base for asset URLs.
	 */
	protected $module_url;

	/**
	 * @var string Plugin version used as asset cache buster.
	 */
	protected $plugin_version;

	public function __construct( Blaminhor_Essentials_Cookies_Consent_Manager $consent, array $settings, $module_url, $plugin_version ) {
		$this->consent        = $consent;
		$this->settings       = $settings;
		$this->module_url     = trailingslashit( $module_url );
		$this->plugin_version = $plugin_version;
	}

	/**
	 * Register front-end hooks.
	 */
	public function register_hooks() {
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ), 9 );
		add_action( 'wp_footer', array( $this, 'render_root_container' ), 100 );
	}

	/**
	 * Admin-only preview request: skip hide_for_admins and force banner render.
	 *
	 * Guarded by capability + nonce so a non-admin cannot trigger preview mode.
	 *
	 * @return bool
	 */
	public function is_preview_request() {
		if ( empty( $_GET['blaminhor_preview_banner'] ) ) {
			return false;
		}
		if ( ! current_user_can( 'manage_options' ) ) {
			return false;
		}
		$nonce = isset( $_GET['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ) : '';
		return (bool) wp_verify_nonce( $nonce, 'blaminhor_essentials_cookies_preview' );
	}

	/**
	 * Decide what to enqueue based on the consent state.
	 */
	public function enqueue_assets() {
		// Don't load on admin previews / customizer / login pages.
		if ( is_admin() ) {
			return;
		}

		$is_preview    = $this->is_preview_request();
		$valid_consent = $is_preview ? false : $this->consent->read_cookie();

		// Hide for logged-in admins if the setting requests it — except in preview mode.
		if ( ! $is_preview && ! empty( $this->settings['hide_for_admins'] ) && current_user_can( 'manage_options' ) ) {
			return;
		}

		$config = $this->build_runtime_config( $valid_consent );

		// Inline config as a static JSON island — keeps the HTML cacheable.
		wp_register_script( 'blaminhor-cookies-config', '', array(), $this->plugin_version, false );
		wp_enqueue_script( 'blaminhor-cookies-config' );
		wp_add_inline_script(
			'blaminhor-cookies-config',
			'window.blaminhorCookiesConfig=' . wp_json_encode( $config ) . ';',
			'before'
		);

		// Zero-byte fast-path: visitor already consented.
		if ( $valid_consent ) {
			wp_add_inline_script(
				'blaminhor-cookies-config',
				sprintf(
					'window.blaminhorConsent=%s;',
					wp_json_encode(
						array(
							'choices'        => $valid_consent['choices'],
							'services'       => $valid_consent['services'],
							'policy_version' => $valid_consent['policy_version'],
							'lang'           => $valid_consent['lang'],
						)
					)
				),
				'after'
			);
			return;
		}

		// Full banner runtime.
		wp_enqueue_style(
			'blaminhor-cookies-banner',
			$this->module_url . 'assets/css/banner.css',
			array(),
			$this->plugin_version
		);
		wp_enqueue_script(
			'blaminhor-cookies-banner',
			$this->module_url . 'assets/js/banner.js',
			array( 'blaminhor-cookies-config' ),
			$this->plugin_version,
			true
		);

		// TCF v2.2 runtime if enabled.
		if ( ! empty( $this->settings['tcf_enabled'] ) ) {
			wp_enqueue_script(
				'blaminhor-cookies-tcf',
				$this->module_url . 'assets/js/tcf-api.js',
				array( 'blaminhor-cookies-banner' ),
				$this->plugin_version,
				true
			);
		}
	}

	/**
	 * Mount point for the banner Shadow DOM.
	 */
	public function render_root_container() {
		if ( is_admin() ) {
			return;
		}
		// The runtime decides whether to render content inside this host.
		echo '<div id="blaminhor-cookies-root" data-blaminhor-cookies></div>';
	}

	/**
	 * Build the runtime config JSON. Same payload for every visitor (cacheable).
	 *
	 * @param array|false $existing_consent Active consent payload or false.
	 * @return array
	 */
	public function build_runtime_config( $existing_consent ) {
		$rest_root = esc_url_raw( rest_url( 'blaminhor-essentials/cookies/v1/' ) );
		$nonce     = wp_create_nonce( 'wp_rest' );

		$config = array(
			'version'        => $this->plugin_version,
			'policyVersion'  => $this->consent->get_policy_version(),
			'restRoot'       => $rest_root,
			'restNonce'      => $nonce,
			'cookieName'     => Blaminhor_Essentials_Cookies_Consent_Manager::COOKIE_NAME,
			'cookieTtlDays'  => (int) ceil( Blaminhor_Essentials_Cookies_Consent_Manager::COOKIE_TTL / DAY_IN_SECONDS ),
			'categories'     => $this->consent->get_categories(),
			'hasConsent'     => (bool) $existing_consent,
			'layout'         => $this->settings['layout'] ?? 'banner-bottom',
			'darkMode'       => $this->settings['dark_mode'] ?? 'auto',
			'symmetryLock'   => ! empty( $this->settings['symmetry_lock'] ),
			'showRevokeIcon' => ! empty( $this->settings['show_revoke_icon'] ),
			'colors'         => array(
				'background'      => $this->settings['color_bg'] ?? '#ffffff',
				'text'            => $this->settings['color_text'] ?? '#1f2329',
				'buttonBg'        => $this->settings['color_button_bg'] ?? '#1d4ed8',
				'buttonText'      => $this->settings['color_button_text'] ?? '#ffffff',
				'buttonBorder'    => $this->settings['color_button_border'] ?? '#1d4ed8',
				'darkBackground'  => $this->settings['color_dark_bg'] ?? '#1f2329',
				'darkText'        => $this->settings['color_dark_text'] ?? '#f5f6f7',
			),
			'texts'          => $this->build_runtime_texts(),
			'gcmEnabled'     => ! empty( $this->settings['gcm_enabled'] ),
			'tcfEnabled'     => ! empty( $this->settings['tcf_enabled'] ),
			'services'       => apply_filters( 'blaminhor_cookies_runtime_services', array() ),
			'previewMode'    => $this->is_preview_request(),
		);

		return apply_filters( 'blaminhor_cookies_runtime_config', $config, $existing_consent );
	}

	/**
	 * All translatable strings shipped to the browser runtime.
	 *
	 * @return array
	 */
	protected function build_runtime_texts() {
		return array(
			'banner_title'        => __( 'We respect your privacy', 'blaminhor-essentials' ),
			'banner_body'         => __( 'This site uses cookies for essential operation, audience measurement and, optionally, marketing. You can accept all, reject all, or customize your choices.', 'blaminhor-essentials' ),
			'accept_all'          => __( 'Accept all', 'blaminhor-essentials' ),
			'reject_all'          => __( 'Reject all', 'blaminhor-essentials' ),
			'customize'           => __( 'Customize', 'blaminhor-essentials' ),
			'save_preferences'    => __( 'Save my choices', 'blaminhor-essentials' ),
			'preferences_title'   => __( 'Cookie preferences', 'blaminhor-essentials' ),
			'category_essential'  => __( 'Essential', 'blaminhor-essentials' ),
			'category_essential_desc' => __( 'Required for the site to function. Cannot be disabled.', 'blaminhor-essentials' ),
			'category_preferences'    => __( 'Preferences', 'blaminhor-essentials' ),
			'category_preferences_desc' => __( 'Remember your choices (language, theme, region).', 'blaminhor-essentials' ),
			'category_statistics'     => __( 'Statistics', 'blaminhor-essentials' ),
			'category_statistics_desc' => __( 'Measure audience and improve the site (Google Analytics, Matomo).', 'blaminhor-essentials' ),
			'category_marketing'      => __( 'Marketing', 'blaminhor-essentials' ),
			'category_marketing_desc' => __( 'Personalized advertising and tracking across sites (Meta Pixel, Google Ads, TikTok).', 'blaminhor-essentials' ),
			'enabled'             => __( 'Enabled', 'blaminhor-essentials' ),
			'disabled'            => __( 'Disabled', 'blaminhor-essentials' ),
			'always_active'       => __( 'Always active', 'blaminhor-essentials' ),
			'revoke_button'       => __( 'Cookie settings', 'blaminhor-essentials' ),
			'close'               => __( 'Close', 'blaminhor-essentials' ),
			'iframe_blocked'      => __( 'External content blocked. Accept marketing cookies to load this content.', 'blaminhor-essentials' ),
			'iframe_load_once'    => __( 'Load this content once', 'blaminhor-essentials' ),
			'iframe_load_always'  => __( 'Always load content from this provider', 'blaminhor-essentials' ),
			'gpc_acknowledged'    => __( 'Your browser sent a Global Privacy Control signal — non-essential cookies have been refused automatically.', 'blaminhor-essentials' ),
			'dnsmpi_link'         => __( 'Do Not Sell or Share My Personal Information', 'blaminhor-essentials' ),
			'show_details'        => __( 'Show services', 'blaminhor-essentials' ),
			'hide_details'        => __( 'Hide services', 'blaminhor-essentials' ),
			'privacy_policy'      => __( 'Privacy policy', 'blaminhor-essentials' ),
			'preview_banner'      => __( 'Preview mode — your choices are not saved', 'blaminhor-essentials' ),
			'preview_exit'        => __( 'Exit preview', 'blaminhor-essentials' ),
		);
	}
}
