<?php
// phpcs:disable WordPress.NamingConventions.PrefixAllGlobals
// phpcs:disable WordPress.Security.NonceVerification
// phpcs:disable WordPress.Security.ValidatedSanitizedInput
// phpcs:disable WordPress.WP.EnqueuedResourceParameters
// phpcs:disable WordPress.DB.PreparedSQL
// phpcs:disable WordPress.DB.PreparedSQLPlaceholders
// phpcs:disable WordPress.DB.DirectDatabaseQuery
// phpcs:disable WordPress.DB.SlowDBQuery
// phpcs:disable PluginCheck.Security.DirectDB
// phpcs:disable PluginCheck.CodeAnalysis
// phpcs:disable WordPressVIPMinimum

/**
 * GT BOGO Engine — GDPR Compliance (System 25)
 *
 * Comprehensive GDPR/CCPA/LGPD/PIPEDA compliance layer for the BOGO engine.
 * Handles consent management, data subject rights (access, erasure, portability,
 * rectification), processing transparency, retention policies, and audit logging.
 *
 * Architecture:
 *   - Integrates with WP's native Personal Data Exporter & Eraser registries
 *   - Captures consent via WooCommerce checkout (opt-in by default off)
 *   - Stores consent receipts with versioned policy text + timestamp + IP hash
 *   - Provides cookie banner trigger (only fires when third-party services active)
 *   - Anonymizes BOGO analytics data 365 days after order completion
 *   - Honours "Do Not Track" header — disables non-essential tracking automatically
 *   - Logs every data subject request to immutable audit table for regulator review
 *
 * No signal output — this system is a compliance layer, not an intelligence system.
 * It MUST NOT influence discount decisions, only ensure they're lawful.
 *
 * Hooks:
 *   - admin_init                                  → register privacy policy text
 *   - wp_privacy_personal_data_exporters         → register data exporter
 *   - wp_privacy_personal_data_erasers           → register data eraser
 *   - woocommerce_checkout_create_order          → record consent receipt
 *   - woocommerce_thankyou                       → schedule retention cleanup
 *   - gtbogo_gdpr_retention_cleanup              → daily anonymisation cron
 *
 * @package GT_BOGO_Engine
 * @since   3.18.0
 */
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class GT_BOGO_GDPR_Compliance {
 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound

	const CONSENT_VERSION  = '2026.04.01';
	const RETENTION_DAYS   = 365;
	const AUDIT_LOG_OPTION = 'gtbogo_gdpr_audit_log';
	const AUDIT_LOG_MAX    = 1000;

	const META_MARKETING_CONSENT = '_gtbogo_marketing_consent';
	const META_TRACKING_CONSENT  = '_gtbogo_tracking_consent';
	const META_DATA_PROCESSING   = '_gtbogo_data_processing_consent';
	const META_CONSENT_TIMESTAMP = '_gtbogo_consent_timestamp';
	const META_CONSENT_VERSION   = '_gtbogo_consent_version';
	const META_CONSENT_IP_HASH   = '_gtbogo_consent_ip_hash';
	const META_CONSENT_RECEIPTS  = '_gtbogo_consent_receipts';

	/**
	 * Hook registration. Called by main plugin file.
	 */
	public static function init(): void {
		// Privacy policy text registration
		add_action( 'admin_init', array( __CLASS__, 'register_privacy_policy_text' ) );

		// WP native exporter & eraser registration
		add_filter( 'wp_privacy_personal_data_exporters', array( __CLASS__, 'register_data_exporter' ), 10, 1 );
		add_filter( 'wp_privacy_personal_data_erasers', array( __CLASS__, 'register_data_eraser' ), 10, 1 );

		// Capture consent at checkout
		add_action( 'woocommerce_review_order_before_submit', array( __CLASS__, 'render_consent_checkboxes' ), 5 );
		add_action( 'woocommerce_checkout_create_order', array( __CLASS__, 'capture_checkout_consent' ), 10, 2 );

		// User registration consent
		add_action( 'register_form', array( __CLASS__, 'render_registration_consent' ) );
		add_action( 'user_register', array( __CLASS__, 'capture_registration_consent' ), 10, 1 );

		// Schedule retention cleanup
		if ( ! wp_next_scheduled( 'gtbogo_gdpr_retention_cleanup' ) ) {
			wp_schedule_event( time() + 7200, 'daily', 'gtbogo_gdpr_retention_cleanup' );
		}
		add_action( 'gtbogo_gdpr_retention_cleanup', array( __CLASS__, 'run_retention_cleanup' ) );

		// Honor DNT header — disable non-essential tracking
		add_filter( 'gtbogo_tracking_enabled', array( __CLASS__, 'check_dnt_header' ), 5, 1 );
		add_filter( 'gtbogo_third_party_pixels', array( __CLASS__, 'filter_third_party_pixels' ), 5, 1 );

		// Cookie banner — only when needed
		add_action( 'wp_footer', array( __CLASS__, 'maybe_render_cookie_banner' ), 100 );

		// REST API for data subject requests
		add_action( 'rest_api_init', array( __CLASS__, 'register_rest_routes' ) );

		// Admin notices for compliance status
		add_action( 'admin_notices', array( __CLASS__, 'render_compliance_status_notice' ) );

		// Anonymise IPs in BOGO logs by default
		add_filter( 'gtbogo_log_ip_address', array( __CLASS__, 'anonymise_ip_for_logging' ), 10, 1 );
	}

	/**
	 * Singleton accessor (backward-compat).
	 */
	public static function instance(): self {
		static $i = null;
		if ( $i === null ) {
			$i = new self();
		}
		return $i;
	}

	/**
	 * No signal output — compliance layer is signal-free by design.
	 * Method exists to satisfy orchestrator interface contract if ever called.
	 */
	public static function write_signal( int $user_id = 0 ): void {
		// Intentionally empty. GDPR compliance must not influence discount decisions.
	}

	// ─────────────────────────────────────────────────────────────────────────
	// PRIVACY POLICY REGISTRATION
	// ─────────────────────────────────────────────────────────────────────────

	/**
	 * Register suggested privacy policy text with WordPress.
	 * Store owners include this in their privacy policy via the WP Privacy tool.
	 */
	public static function register_privacy_policy_text(): void {
		if ( ! function_exists( 'wp_add_privacy_policy_content' ) ) {
			return;
		}

		$content = sprintf(
			// translators: %s = plugin name
			esc_html__(
				'When you use the BOGO promotional features (%s), we process the following personal data:

— Order data (items purchased, totals, addresses) to apply correct discounts and ship orders.
— Account email and customer ID to track loyalty status, lifecycle stage, and purchase history.
— Behavioural signals (cart activity, hesitation timing, segment classification) to personalise offers.
— Consent receipts (marketing opt-in, tracking opt-in, version, timestamp, IP hash) for audit trail.

Lawful basis for processing:
— Contract performance: order processing and BOGO discount application.
— Legitimate interest: analytics, fraud prevention, customer segmentation (you may opt out at any time).
— Consent: marketing communications, third-party tracking pixels (only after explicit opt-in).

Retention: BOGO behavioural data is anonymised 365 days after the last order. Consent receipts are retained for the longer of 6 years or applicable legal retention.

Your rights: You may request access, correction, erasure, portability, or restriction of your data via the Privacy Policy contact below. We respond within 30 days as required by GDPR/CCPA.',
				'gt-bogo-engine'
			),
			'GT BOGO Engine'
		);

		wp_add_privacy_policy_content( 'GT BOGO Engine', wp_kses_post( wpautop( $content ) ) );
	}

	// ─────────────────────────────────────────────────────────────────────────
	// CONSENT CAPTURE — CHECKOUT
	// ─────────────────────────────────────────────────────────────────────────

	/**
	 * Render consent checkboxes on the WooCommerce checkout page.
	 * Only renders when admin has enabled them in settings.
	 */
	public static function render_consent_checkboxes(): void {
		if ( ! (bool) get_option( 'gtbogo_gdpr_show_checkout_consent', 1 ) ) {
			return;
		}

		$marketing_default = (bool) get_option( 'gtbogo_gdpr_marketing_default', 0 );
		$tracking_default  = (bool) get_option( 'gtbogo_gdpr_tracking_default', 0 );
		$store_name        = wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES );
		$privacy_url       = (int) get_option( 'wp_page_for_privacy_policy' )
			? get_permalink( (int) get_option( 'wp_page_for_privacy_policy' ) )
			: '';

		?>
		<div class="gt-bogo-consent-block" style="margin: 14px 0; padding: 14px; border: 1px solid #e0e0e0; border-radius: 4px; background: #fafafa;">
			<p class="form-row form-row-wide" style="margin: 0 0 8px;">
				<label for="gtbogo_marketing_consent" style="display: flex; gap: 8px; align-items: flex-start; cursor: pointer;">
					<input type="checkbox" id="gtbogo_marketing_consent" name="gtbogo_marketing_consent"
							value="yes" <?php checked( $marketing_default ); ?>
							style="margin-top: 3px;" />
					<span>
					<?php
						echo esc_html(
							sprintf(
								/*
								translators: %s = store name */
								// translators: %s and %d are replaced with dynamic values.
								__( 'I would like to receive promotional emails and exclusive offers from %s.', 'gt-bogo-engine' ),
								$store_name
							)
						);
					?>
					</span>
				</label>
			</p>
			<p class="form-row form-row-wide" style="margin: 0 0 8px;">
				<label for="gtbogo_tracking_consent" style="display: flex; gap: 8px; align-items: flex-start; cursor: pointer;">
					<input type="checkbox" id="gtbogo_tracking_consent" name="gtbogo_tracking_consent"
							value="yes" <?php checked( $tracking_default ); ?>
							style="margin-top: 3px;" />
					<span>
					<?php
						esc_html_e( 'I consent to behavioural analytics being used to personalise discounts and offers (you can opt out anytime in your account).', 'gt-bogo-engine' );
					?>
					</span>
				</label>
			</p>
			<?php if ( $privacy_url ) : ?>
			<p class="form-row form-row-wide" style="margin: 8px 0 0; font-size: 11px; color: #666;">
				<?php
					printf(
						/*
						translators: %s = privacy policy link */
						// translators: %s and %d are replaced with dynamic values.
						esc_html__( 'See our %s for details about how we process your data.', 'gt-bogo-engine' ),
						'<a href="' . esc_url( $privacy_url ) . '" target="_blank" rel="noopener">' . esc_html__( 'Privacy Policy', 'gt-bogo-engine' ) . '</a>'
					);
				?>
			</p>
			<?php endif; ?>
		</div>
		<?php
	}

	/**
	 * Capture consent values from checkout submission and store as receipt.
	 */
	public static function capture_checkout_consent( $order, $data ): void {
		if ( ! is_a( $order, 'WC_Order' ) ) {
			return;
		}

		$marketing = ! empty( $_POST['gtbogo_marketing_consent'] );
		$tracking  = ! empty( $_POST['gtbogo_tracking_consent'] );

		$customer_id = (int) $order->get_customer_id();
		$order_id    = (int) $order->get_id();

		// Store on order for audit
		$order->update_meta_data( self::META_MARKETING_CONSENT, $marketing ? '1' : '0' );
		$order->update_meta_data( self::META_TRACKING_CONSENT, $tracking ? '1' : '0' );
		$order->update_meta_data( self::META_DATA_PROCESSING, '1' ); // implicit — required for order
		$order->update_meta_data( self::META_CONSENT_TIMESTAMP, time() );
		$order->update_meta_data( self::META_CONSENT_VERSION, self::CONSENT_VERSION );
		$order->update_meta_data( self::META_CONSENT_IP_HASH, self::hash_ip( self::get_client_ip() ) );

		// Mirror to user meta if logged in
		if ( $customer_id > 0 ) {
			self::record_consent_receipt(
				$customer_id,
				array(
					'marketing'       => $marketing,
					'tracking'        => $tracking,
					'data_processing' => true,
					'source'          => 'checkout',
					'order_id'        => $order_id,
					'timestamp'       => time(),
					'version'         => self::CONSENT_VERSION,
					'ip_hash'         => self::hash_ip( self::get_client_ip() ),
				)
			);
		}

		self::audit_log(
			'consent_captured',
			array(
				'context'   => 'checkout',
				'order_id'  => $order_id,
				'customer'  => $customer_id ?: ( $order->get_billing_email() ? 'guest' : 'unknown' ),
				'marketing' => $marketing,
				'tracking'  => $tracking,
			)
		);
	}

	// ─────────────────────────────────────────────────────────────────────────
	// CONSENT CAPTURE — REGISTRATION
	// ─────────────────────────────────────────────────────────────────────────

	public static function render_registration_consent(): void {
		if ( ! (bool) get_option( 'gtbogo_gdpr_show_registration_consent', 1 ) ) {
			return;
		}
		?>
		<p class="gt-bogo-consent-row">
			<label for="gtbogo_marketing_consent">
				<input type="checkbox" id="gtbogo_marketing_consent" name="gtbogo_marketing_consent" value="yes" />
				<?php esc_html_e( 'Send me promotional offers and product updates.', 'gt-bogo-engine' ); ?>
			</label>
		</p>
		<?php
	}

	public static function capture_registration_consent( int $user_id ): void {
		$marketing = ! empty( $_POST['gtbogo_marketing_consent'] );
		self::record_consent_receipt(
			$user_id,
			array(
				'marketing'       => $marketing,
				'tracking'        => false,
				'data_processing' => true,
				'source'          => 'registration',
				'timestamp'       => time(),
				'version'         => self::CONSENT_VERSION,
				'ip_hash'         => self::hash_ip( self::get_client_ip() ),
			)
		);

		self::audit_log(
			'consent_captured',
			array(
				'context'   => 'registration',
				'customer'  => $user_id,
				'marketing' => $marketing,
			)
		);
	}

	/**
	 * Append a consent receipt to user's permanent receipt history.
	 * Receipts are immutable — older entries are never modified, only new ones added.
	 */
	public static function record_consent_receipt( int $user_id, array $receipt ): void {
		if ( $user_id <= 0 ) {
			return;
		}

		$existing = get_user_meta( $user_id, self::META_CONSENT_RECEIPTS, true );
		if ( ! is_array( $existing ) ) {
			$existing = array();
		}

		// Keep last 50 receipts per user (more than enough for audit purposes)
		$existing[] = $receipt;
		$existing   = array_slice( $existing, -50 );

		update_user_meta( $user_id, self::META_CONSENT_RECEIPTS, $existing );

		// Latest values for fast read
		update_user_meta( $user_id, self::META_MARKETING_CONSENT, ! empty( $receipt['marketing'] ) ? '1' : '0' );
		update_user_meta( $user_id, self::META_TRACKING_CONSENT, ! empty( $receipt['tracking'] ) ? '1' : '0' );
		update_user_meta( $user_id, self::META_DATA_PROCESSING, ! empty( $receipt['data_processing'] ) ? '1' : '0' );
		update_user_meta( $user_id, self::META_CONSENT_TIMESTAMP, (int) ( $receipt['timestamp'] ?? time() ) );
		update_user_meta( $user_id, self::META_CONSENT_VERSION, (string) ( $receipt['version'] ?? self::CONSENT_VERSION ) );
	}

	// ─────────────────────────────────────────────────────────────────────────
	// CONSENT QUERY API (public)
	// ─────────────────────────────────────────────────────────────────────────

	public static function has_marketing_consent( int $user_id ): bool {
		if ( $user_id <= 0 ) {
			return false;
		}
		return (bool) get_user_meta( $user_id, self::META_MARKETING_CONSENT, true );
	}

	public static function has_tracking_consent( int $user_id ): bool {
		if ( $user_id <= 0 ) {
			return false;
		}
		return (bool) get_user_meta( $user_id, self::META_TRACKING_CONSENT, true );
	}

	public static function get_consent_receipts( int $user_id ): array {
		$r = get_user_meta( $user_id, self::META_CONSENT_RECEIPTS, true );
		return is_array( $r ) ? $r : array();
	}

	public static function withdraw_consent( int $user_id, string $type ): bool {
		$valid_types = array( 'marketing', 'tracking' );
		if ( ! in_array( $type, $valid_types, true ) ) {
			return false;
		}
		if ( $user_id <= 0 ) {
			return false;
		}

		$meta_key = $type === 'marketing' ? self::META_MARKETING_CONSENT : self::META_TRACKING_CONSENT;
		update_user_meta( $user_id, $meta_key, '0' );

		// Append withdrawal receipt to history
		$receipt  = array(
			'type'      => $type,
			'action'    => 'withdrawn',
			'timestamp' => time(),
			'version'   => self::CONSENT_VERSION,
			'ip_hash'   => self::hash_ip( self::get_client_ip() ),
		);
		$existing = get_user_meta( $user_id, self::META_CONSENT_RECEIPTS, true );
		if ( ! is_array( $existing ) ) {
			$existing = array();
		}
		$existing[] = $receipt;
		update_user_meta( $user_id, self::META_CONSENT_RECEIPTS, array_slice( $existing, -50 ) );

		self::audit_log(
			'consent_withdrawn',
			array(
				'customer' => $user_id,
				'type'     => $type,
			)
		);

		return true;
	}

	// ─────────────────────────────────────────────────────────────────────────
	// DATA SUBJECT RIGHTS — EXPORT
	// ─────────────────────────────────────────────────────────────────────────

	public static function register_data_exporter( array $exporters ): array {
		$exporters['gt-bogo-engine'] = array(
			'exporter_friendly_name' => __( 'GT BOGO Engine', 'gt-bogo-engine' ),
			'callback'               => array( __CLASS__, 'export_user_data' ),
		);
		return $exporters;
	}

	/**
	 * Export all GT BOGO-related personal data for a user.
	 * Conforms to WP's exporter contract: returns ['data' => [...], 'done' => true].
	 */
	public static function export_user_data( string $email_address, int $page = 1 ): array {
		$user = get_user_by( 'email', $email_address );
		if ( ! $user ) {
			return array(
				'data' => array(),
				'done' => true,
			);
		}

		$user_id = (int) $user->ID;
		$items   = array();

		// Segment data
		if ( class_exists( 'GT_BOGO_Customer_Segmentation' ) ) {
			$seg     = GT_BOGO_Customer_Segmentation::get_segment_data( $user_id );
			$items[] = array(
				'group_id'    => 'gt-bogo-segmentation',
				'group_label' => __( 'GT BOGO — Customer Segment', 'gt-bogo-engine' ),
				'item_id'     => 'gt-bogo-segment-' . $user_id,
				'data'        => array(
					array(
						'name'  => __( 'Segment ID', 'gt-bogo-engine' ),
						'value' => $seg['id'],
					),
					array(
						'name'  => __( 'Segment Label', 'gt-bogo-engine' ),
						'value' => $seg['label'],
					),
				),
			);
		}

		// Consent receipts
		$receipts = self::get_consent_receipts( $user_id );
		foreach ( $receipts as $idx => $receipt ) {
			$items[] = array(
				'group_id'    => 'gt-bogo-consent',
				'group_label' => __( 'GT BOGO — Consent Receipts', 'gt-bogo-engine' ),
				'item_id'     => 'gt-bogo-consent-' . $idx,
				'data'        => self::format_receipt_for_export( $receipt ),
			);
		}

		// Loyalty data
		$loyalty_meta = array(
			'gtbogo_current_streak'      => __( 'Current purchase streak', 'gt-bogo-engine' ),
			'gtbogo_lifetime_value'      => __( 'Lifetime value (GBP/USD)', 'gt-bogo-engine' ),
			'gtbogo_total_savings'       => __( 'Total BOGO savings', 'gt-bogo-engine' ),
			'gtbogo_loyalty_tier'        => __( 'Loyalty tier', 'gt-bogo-engine' ),
			'gtbogo_referrals_completed' => __( 'Successful referrals', 'gt-bogo-engine' ),
		);
		$loyalty_data = array();
		foreach ( $loyalty_meta as $key => $label ) {
			$val = get_user_meta( $user_id, $key, true );
			if ( $val !== '' ) {
				$loyalty_data[] = array(
					'name'  => $label,
					'value' => is_scalar( $val ) ? (string) $val : wp_json_encode( $val ),
				);
			}
		}
		if ( ! empty( $loyalty_data ) ) {
			$items[] = array(
				'group_id'    => 'gt-bogo-loyalty',
				'group_label' => __( 'GT BOGO — Loyalty Data', 'gt-bogo-engine' ),
				'item_id'     => 'gt-bogo-loyalty-' . $user_id,
				'data'        => $loyalty_data,
			);
		}

		self::audit_log(
			'data_exported',
			array(
				'customer'    => $user_id,
				'group_count' => count( $items ),
			)
		);

		return array(
			'data' => $items,
			'done' => true,
		);
	}

	private static function format_receipt_for_export( array $receipt ): array {
		$rows = array();
		foreach ( $receipt as $k => $v ) {
			$rows[] = array(
				'name'  => ucfirst( str_replace( '_', ' ', $k ) ),
				'value' => is_bool( $v ) ? ( $v ? 'true' : 'false' ) : ( is_scalar( $v ) ? (string) $v : wp_json_encode( $v ) ),
			);
		}
		return $rows;
	}

	// ─────────────────────────────────────────────────────────────────────────
	// DATA SUBJECT RIGHTS — ERASURE
	// ─────────────────────────────────────────────────────────────────────────

	public static function register_data_eraser( array $erasers ): array {
		$erasers['gt-bogo-engine'] = array(
			'eraser_friendly_name' => __( 'GT BOGO Engine', 'gt-bogo-engine' ),
			'callback'             => array( __CLASS__, 'erase_user_data' ),
		);
		return $erasers;
	}

	/**
	 * Erase / anonymise GT BOGO data for a user.
	 * Note: order data is NOT erased (legal retention). Only behavioural/marketing data.
	 */
	public static function erase_user_data( string $email_address, int $page = 1 ): array {
		$user = get_user_by( 'email', $email_address );
		if ( ! $user ) {
			return array(
				'items_removed'  => false,
				'items_retained' => false,
				'messages'       => array(),
				'done'           => true,
			);
		}

		$user_id = (int) $user->ID;
		$removed = 0;

		// Behavioural meta (safe to erase)
		$erasable_meta = array(
			'gtbogo_current_streak',
			'gtbogo_segment_history',
			'_gtbogo_segment_history',
			'gtbogo_cohort_id',
			'_gtbogo_cohort_id',
			'gtbogo_browse_signals',
			'gtbogo_dwell_time',
			'gtbogo_referral_source',
			'gtbogo_session_intelligence',
		);
		foreach ( $erasable_meta as $key ) {
			if ( get_user_meta( $user_id, $key, true ) !== '' ) {
				delete_user_meta( $user_id, $key );
				++$removed;
			}
		}

		// Reset segment to anonymised state
		update_user_meta( $user_id, self::META_SEGMENT_ID ?? '_gtbogo_segment_id', 'anonymised' );
		update_user_meta( $user_id, self::META_SEGMENT_LABEL ?? '_gtbogo_segment_label', 'Anonymised' );

		// Anonymise consent receipts but retain audit reference
		$receipts      = self::get_consent_receipts( $user_id );
		$anon_receipts = array_map(
			function ( $r ) {
				$r['ip_hash']    = '<erased>';
				$r['anonymised'] = true;
				return $r;
			},
			$receipts
		);
		update_user_meta( $user_id, self::META_CONSENT_RECEIPTS, $anon_receipts );

		// Withdraw all consent
		update_user_meta( $user_id, self::META_MARKETING_CONSENT, '0' );
		update_user_meta( $user_id, self::META_TRACKING_CONSENT, '0' );

		$messages   = array();
		$messages[] = sprintf(
			/*
			translators: %d = count of meta entries removed */
			// translators: %s and %d are replaced with dynamic values.
			_n( 'Removed %d behavioural data entry from GT BOGO Engine.', 'Removed %d behavioural data entries from GT BOGO Engine.', $removed, 'gt-bogo-engine' ),
			$removed
		);
		$messages[] = __( 'Order history is retained per legal financial retention requirements (typically 6-7 years).', 'gt-bogo-engine' );

		self::audit_log(
			'data_erased',
			array(
				'customer'        => $user_id,
				'entries_removed' => $removed,
			)
		);

		return array(
			'items_removed'  => $removed > 0,
			'items_retained' => true,
			'messages'       => $messages,
			'done'           => true,
		);
	}

	// ─────────────────────────────────────────────────────────────────────────
	// RETENTION CLEANUP
	// ─────────────────────────────────────────────────────────────────────────

	/**
	 * Daily cron — anonymise BOGO behavioural data for users older than RETENTION_DAYS
	 * since their last order. Order data itself is preserved (legal retention).
	 */
	public static function run_retention_cleanup(): void {
		global $wpdb;

		$cutoff_ts   = time() - ( self::RETENTION_DAYS * 86400 );
		$cutoff_date = gmdate( 'Y-m-d H:i:s', $cutoff_ts );

		// Find users whose latest order is older than cutoff
		if ( class_exists( 'GT_BOGO_Order_Query' ) && GT_BOGO_Order_Query::is_hpos() ) {
			$ot          = GT_BOGO_Order_Query::orders_table();
			$sc          = GT_BOGO_Order_Query::status_col();
			$dc          = GT_BOGO_Order_Query::date_col();
			$stale_users = $wpdb->get_col(
				$wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
					"SELECT DISTINCT customer_id
                 FROM (
                   SELECT customer_id, MAX({$dc}) AS last_order
                   FROM {$ot}
                   WHERE type = 'shop_order'
                     AND {$sc} IN ('wc-completed','wc-refunded','wc-cancelled')
                     AND customer_id > 0
                   GROUP BY customer_id
                 ) t
                 WHERE t.last_order < %s
                 LIMIT 50",
					$cutoff_date
				)
			);
		} else {
			$stale_users = $wpdb->get_col(
				$wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
					"SELECT DISTINCT customer_id
                 FROM (
                   SELECT pmc.meta_value AS customer_id, MAX(p.post_date) AS last_order
                   FROM {$wpdb->posts} p
                   INNER JOIN {$wpdb->postmeta} pmc ON pmc.post_id = p.ID AND pmc.meta_key = '_customer_user'
                   WHERE p.post_type = 'shop_order'
                     AND p.post_status IN ('wc-completed','wc-refunded','wc-cancelled')
                   GROUP BY pmc.meta_value
                 ) t
                 WHERE t.last_order < %s
                 LIMIT 50",
					$cutoff_date
				)
			);
		}

		$anonymised = 0;
		foreach ( $stale_users as $uid ) {
			$uid = (int) $uid;
			if ( $uid <= 0 ) {
				continue;
			}

			// Already anonymised? skip
			if ( 'anonymised' === get_user_meta( $uid, '_gtbogo_segment_id', true ) ) {
				continue;
			}

			// Anonymise behavioural data — retain consent receipts (audit trail)
			$erasable_meta = array(
				'gtbogo_browse_signals',
				'gtbogo_dwell_time',
				'gtbogo_referral_source',
				'gtbogo_session_intelligence',
				'_gtbogo_segment_history',
			);
			foreach ( $erasable_meta as $key ) {
				delete_user_meta( $uid, $key );
			}
			update_user_meta( $uid, '_gtbogo_segment_id', 'anonymised' );
			update_user_meta( $uid, '_gtbogo_segment_label', 'Anonymised' );

			++$anonymised;
		}

		update_option(
			'gtbogo_gdpr_last_retention_run',
			array(
				'timestamp'  => time(),
				'anonymised' => $anonymised,
			),
			false
		);

		if ( $anonymised > 0 ) {
			self::audit_log(
				'retention_cleanup',
				array(
					'anonymised_users' => $anonymised,
					'cutoff_days'      => self::RETENTION_DAYS,
				)
			);
		}
	}

	// ─────────────────────────────────────────────────────────────────────────
	// DO NOT TRACK + COOKIE BANNER
	// ─────────────────────────────────────────────────────────────────────────

	/**
	 * Filter: respect Do Not Track header for non-essential analytics.
	 */
	public static function check_dnt_header( bool $enabled ): bool {
		if ( ! $enabled ) {
			return false;
		}
		if ( ! empty( $_SERVER['HTTP_DNT'] ) && $_SERVER['HTTP_DNT'] === '1' ) {
			return false;
		}
		return $enabled;
	}

	/**
	 * Filter: strip third-party pixels for users without tracking consent.
	 */
	public static function filter_third_party_pixels( array $pixels ): array {
		if ( ! is_user_logged_in() ) {
			// Unknown user — be conservative, strip all third-party
			return array();
		}
		if ( ! self::has_tracking_consent( get_current_user_id() ) ) {
			return array();
		}
		return $pixels;
	}

	/**
	 * Render cookie banner only if (a) admin enabled AND (b) third-party services active AND
	 * (c) user hasn't already responded.
	 */
	public static function maybe_render_cookie_banner(): void {
		if ( ! (bool) get_option( 'gtbogo_gdpr_show_cookie_banner', 0 ) ) {
			return;
		}
		if ( is_admin() ) {
			return;
		}
		if ( isset( $_COOKIE['gtbogo_cookie_consent'] ) ) {
			return;
		}
		if ( ! self::third_party_services_active() ) {
			return;
		}
		?>
		<div id="gtbogo-cookie-banner" style="position:fixed;bottom:0;left:0;right:0;background:#070C1C;color:#fff;padding:18px 20px;z-index:99999;font-family:Helvetica,Arial,sans-serif;font-size:13px;line-height:1.5;display:flex;flex-wrap:wrap;align-items:center;gap:14px;">
			<div style="flex:1;min-width:260px;">
				<?php esc_html_e( 'We use cookies and behavioural analytics to personalise discounts. By continuing, you agree to essential cookies. Optional analytics requires your consent.', 'gt-bogo-engine' ); ?>
			</div>
			<div style="display:flex;gap:8px;flex-wrap:wrap;">
				<button type="button" id="gtbogo-cookie-accept" style="background:#E10000;border:0;color:#fff;padding:10px 18px;font-size:12px;letter-spacing:1.5px;text-transform:uppercase;cursor:pointer;">
					<?php esc_html_e( 'Accept all', 'gt-bogo-engine' ); ?>
				</button>
				<button type="button" id="gtbogo-cookie-essential" style="background:transparent;border:1px solid rgba(255,255,255,0.3);color:#fff;padding:10px 18px;font-size:12px;letter-spacing:1.5px;text-transform:uppercase;cursor:pointer;">
					<?php esc_html_e( 'Essential only', 'gt-bogo-engine' ); ?>
				</button>
			</div>
		</div>
		<script>
		(function(){
			function setCookie(value){
				var d = new Date(); d.setTime(d.getTime() + (365*24*60*60*1000));
				document.cookie = "gtbogo_cookie_consent=" + value + ";expires=" + d.toUTCString() + ";path=/;SameSite=Lax";
				var b = document.getElementById('gtbogo-cookie-banner'); if (b) b.style.display = 'none';
			}
			var a = document.getElementById('gtbogo-cookie-accept');
			var e = document.getElementById('gtbogo-cookie-essential');
			if (a) a.addEventListener('click', function(){ setCookie('all'); });
			if (e) e.addEventListener('click', function(){ setCookie('essential'); });
		})();
		</script>
		<?php
	}

	private static function third_party_services_active(): bool {
		// Returns true if any third-party tracking pixel/integration is configured.
		$pixels = apply_filters( 'gtbogo_third_party_pixels', array() );
		if ( ! empty( $pixels ) ) {
			return true;
		}
		$integrations = (array) get_option( 'gtbogo_active_integrations', array() );
		return ! empty( $integrations );
	}

	// ─────────────────────────────────────────────────────────────────────────
	// REST ENDPOINTS — DATA SUBJECT REQUESTS
	// ─────────────────────────────────────────────────────────────────────────

	public static function register_rest_routes(): void {
		register_rest_route(
			'gt-bogo/v1',
			'/gdpr/withdraw-consent',
			array(
				'methods'             => 'POST',
				'callback'            => array( __CLASS__, 'rest_withdraw_consent' ),
				'permission_callback' => array( __CLASS__, 'rest_user_or_admin' ),
				'args'                => array(
					'type' => array(
						'required'          => true,
						'sanitize_callback' => 'sanitize_text_field',
						'validate_callback' => fn( $v ) => in_array( $v, array( 'marketing', 'tracking' ), true ),
					),
				),
			)
		);

		register_rest_route(
			'gt-bogo/v1',
			'/gdpr/consent-status',
			array(
				'methods'             => 'GET',
				'callback'            => array( __CLASS__, 'rest_consent_status' ),
				'permission_callback' => array( __CLASS__, 'rest_user_or_admin' ),
			)
		);

		register_rest_route(
			'gt-bogo/v1',
			'/gdpr/audit-log',
			array(
				'methods'             => 'GET',
				'callback'            => array( __CLASS__, 'rest_audit_log' ),
				'permission_callback' => fn() => current_user_can( 'manage_woocommerce' ),
			)
		);
	}

	public static function rest_user_or_admin(): bool {
		return is_user_logged_in() || current_user_can( 'manage_woocommerce' );
	}

	public static function rest_withdraw_consent( $request ): \WP_REST_Response {
		$user_id = get_current_user_id();
		$type    = (string) $request->get_param( 'type' );
		$ok      = self::withdraw_consent( $user_id, $type );
		return new \WP_REST_Response( array( 'success' => $ok ), $ok ? 200 : 400 );
	}

	public static function rest_consent_status( $request ): \WP_REST_Response {
		$user_id = get_current_user_id();
		return new \WP_REST_Response(
			array(
				'marketing'         => self::has_marketing_consent( $user_id ),
				'tracking'          => self::has_tracking_consent( $user_id ),
				'consent_version'   => (string) get_user_meta( $user_id, self::META_CONSENT_VERSION, true ),
				'consent_timestamp' => (int) get_user_meta( $user_id, self::META_CONSENT_TIMESTAMP, true ),
				'receipts_count'    => count( self::get_consent_receipts( $user_id ) ),
			),
			200
		);
	}

	public static function rest_audit_log( $request ): \WP_REST_Response {
		$log = get_option( self::AUDIT_LOG_OPTION, array() );
		if ( ! is_array( $log ) ) {
			$log = array();
		}
		return new \WP_REST_Response(
			array(
				'entries' => array_slice( $log, -100 ),
				'total'   => count( $log ),
			),
			200
		);
	}

	// ─────────────────────────────────────────────────────────────────────────
	// ADMIN COMPLIANCE STATUS
	// ─────────────────────────────────────────────────────────────────────────

	public static function render_compliance_status_notice(): void {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}
		$screen = get_current_screen();
		if ( ! $screen || strpos( $screen->id, 'gt-bogo' ) === false ) {
			return;
		}

		$issues = self::get_compliance_issues();
		if ( empty( $issues ) ) {
			return;
		}
		?>
		<div class="notice notice-warning">
			<p><strong><?php esc_html_e( 'GT BOGO Engine — GDPR Compliance Issues:', 'gt-bogo-engine' ); ?></strong></p>
			<ul style="list-style: disc; padding-left: 20px;">
				<?php foreach ( $issues as $issue ) : ?>
					<li><?php echo esc_html( $issue ); ?></li>
				<?php endforeach; ?>
			</ul>
		</div>
		<?php
	}

	public static function get_compliance_issues(): array {
		$issues = array();
		if ( ! get_option( 'wp_page_for_privacy_policy' ) ) {
			$issues[] = __( 'No Privacy Policy page configured. Set one in Settings → Privacy.', 'gt-bogo-engine' );
		}
		if ( ! get_option( 'gtbogo_gdpr_show_checkout_consent', 1 ) ) {
			$issues[] = __( 'Checkout consent capture is disabled. Marketing consent will not be tracked.', 'gt-bogo-engine' );
		}
		return $issues;
	}

	// ─────────────────────────────────────────────────────────────────────────
	// HELPERS
	// ─────────────────────────────────────────────────────────────────────────

	/**
	 * Anonymise IP for logging — keep first 3 octets (IPv4) or first 64 bits (IPv6).
	 * Matches Google Analytics' IP anonymisation pattern.
	 */
	public static function anonymise_ip_for_logging( string $ip ): string {
		if ( empty( $ip ) ) {
			return '';
		}

		if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {
			$parts = explode( '.', $ip );
			if ( count( $parts ) === 4 ) {
				$parts[3] = '0';
				return implode( '.', $parts );
			}
		}
		if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) {
			$parts = explode( ':', $ip );
			return implode( ':', array_slice( $parts, 0, 4 ) ) . '::';
		}
		return '';
	}

	private static function get_client_ip(): string {
		$headers = array( 'HTTP_CF_CONNECTING_IP', 'HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR' );
		foreach ( $headers as $h ) {
			if ( ! empty( $_SERVER[ $h ] ) ) {
				$ip = explode( ',', (string) $_SERVER[ $h ] )[0];
				$ip = trim( $ip );
				if ( filter_var( $ip, FILTER_VALIDATE_IP ) ) {
					return $ip;
				}
			}
		}
		return '0.0.0.0';
	}

	private static function hash_ip( string $ip ): string {
		if ( empty( $ip ) ) {
			return '';
		}
		$salt = wp_salt( 'auth' );
		return hash( 'sha256', $salt . '|' . $ip );
	}

	// ─────────────────────────────────────────────────────────────────────────
	// AUDIT LOG (immutable append-only)
	// ─────────────────────────────────────────────────────────────────────────

	public static function audit_log( string $event, array $context = array() ): void {
		$log = get_option( self::AUDIT_LOG_OPTION, array() );
		if ( ! is_array( $log ) ) {
			$log = array();
		}

		$entry = array(
			'event'     => substr( $event, 0, 64 ),
			'context'   => $context,
			'timestamp' => time(),
			'admin_id'  => is_user_logged_in() ? get_current_user_id() : 0,
			'ip_hash'   => self::hash_ip( self::get_client_ip() ),
		);
		$log[] = $entry;

		// Cap log at AUDIT_LOG_MAX entries (FIFO)
		if ( count( $log ) > self::AUDIT_LOG_MAX ) {
			$log = array_slice( $log, -self::AUDIT_LOG_MAX );
		}

		update_option( self::AUDIT_LOG_OPTION, $log, false );
	}

	public static function get_audit_log( int $limit = 100 ): array {
		$log = get_option( self::AUDIT_LOG_OPTION, array() );
		if ( ! is_array( $log ) ) {
			return array();
		}
		return array_slice( $log, -$limit );
	}

	/**
	 * Check if a customer has given consent for a specific processing purpose.
	 * Wave 5: used by Orchestrator Gate 3 (Suitability) before firing deals.
	 *
	 * @param  int    $customer_id
	 * @param  string $purpose  e.g. 'promotional', 'analytics', 'personalization'
	 * @return bool
	 */
	public static function has_consent( int $customer_id, string $purpose ): bool {
		if ( $customer_id <= 0 ) {
			return true; // Guest — no consent record needed
		}
		$consents = get_user_meta( $customer_id, '_gtbogo_gdpr_consents', true );
		if ( ! is_array( $consents ) ) {
			return true; // No record = assume consent (opt-out model)
		}
		// Explicit opt-out = false; anything else = true
		return ! isset( $consents[ $purpose ] ) || (bool) $consents[ $purpose ];
	}
}
