<?php
/**
 * Context Capture — Capture client context at checkout for later server events.
 *
 * Problem: Purchase fires server-side (cron) where $_SERVER and $_COOKIE
 * are unavailable. Solution: capture at checkout form submit, store in order meta.
 * Also captures traffic source for analytics segmentation.
 *
 * @package CapiFlow
 */

namespace CapiFlow\Core;

defined( 'ABSPATH' ) || exit;

class Context_Capture {

	/**
	 * Register hooks.
	 */
	public function register_hooks(): void {
		// Primary capture: checkout order creation.
		add_action( 'woocommerce_checkout_create_order', array( $this, 'capture_context' ), 10, 2 );

		// Fallback: REST API / headless checkouts.
		add_action( 'woocommerce_new_order', array( $this, 'capture_on_new_order' ), 10, 2 );
	}

	/**
	 * Capture customer context at checkout form submission.
	 *
	 * @param \WC_Order $order WooCommerce order (not yet saved).
	 * @param array     $data  Checkout form data.
	 */
	public function capture_context( \WC_Order $order, array $data ): void {
		// ── IP Address (CDN/proxy-safe) ──────────────────────────────────────
		$ip = Data_Normalizer::get_real_client_ip();
		if ( '0.0.0.0' !== $ip ) {
			$order->update_meta_data( '_capiflow_client_ip', $ip );
		}

		// ── User Agent ───────────────────────────────────────────────────────
		$ua = Data_Normalizer::get_user_agent();
		if ( ! empty( $ua ) ) {
			$order->update_meta_data( '_capiflow_user_agent', $ua );
		}

		// ── Meta Cookies (fbc, fbp) ──────────────────────────────────────────
		$cookies = Cookie_Manager::get_cookie_data();
		if ( ! empty( $cookies['fbc'] ) ) {
			$order->update_meta_data( '_capiflow_fbc', $cookies['fbc'] );
		}
		if ( ! empty( $cookies['fbp'] ) ) {
			$order->update_meta_data( '_capiflow_fbp', $cookies['fbp'] );
		}

		// ── External ID (CAPI dedup, write-once) ─────────────────────────────
		Cookie_Manager::get_external_id_for_order( $order );

		// ── Source URL (checkout page) ────────────────────────────────────────
		$referer = wp_get_referer();
		$order->update_meta_data(
			'_capiflow_source_url',
			! empty( $referer ) ? esc_url_raw( $referer ) : wc_get_checkout_url()
		);

		// ── Referrer URL (page before checkout, e.g. cart/product page) ──────
		// Meta CAPI optional param: "HTTP referrer header as observed by the
		// page triggering the event. Usually the preceding page in the browser."
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
		$http_referer = isset( $_SERVER['HTTP_REFERER'] ) ? esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : '';
		if ( ! empty( $http_referer ) ) {
			$order->update_meta_data( '_capiflow_referrer_url', $http_referer );
		}

		// ── fbclid from referrer (improves fbc match) ─────────────────────────
		if ( ! empty( $referer ) ) {
			$query = wp_parse_url( $referer, PHP_URL_QUERY );
			if ( $query ) {
				parse_str( $query, $params );
				if ( ! empty( $params['fbclid'] ) ) {
					$order->update_meta_data( '_capiflow_fbclid', sanitize_text_field( $params['fbclid'] ) );
				}
			}
		}

		// ── Traffic Source (for analytics segmentation — A6 addition) ─────────
		$traffic_source = $this->detect_traffic_source();
		$order->update_meta_data( '_capiflow_traffic_source', $traffic_source );

		// Note: meta save happens when WC calls $order->save() automatically.
	}

	/**
	 * Fallback context capture for REST API / programmatic orders.
	 *
	 * Only writes if checkout hook didn't already run (HPOS-compatible check).
	 *
	 * @param int            $order_id Order ID.
	 * @param \WC_Order|null $order    Order object.
	 */
	public function capture_on_new_order( int $order_id, $order = null ): void {
		if ( ! $order instanceof \WC_Order ) {
			$order = wc_get_order( $order_id );
		}

		if ( ! $order ) {
			return;
		}

		// Skip if checkout hook already captured (prevents overwrite).
		if ( ! empty( $order->get_meta( '_capiflow_client_ip', true ) ) ) {
			return;
		}

		$ip = Data_Normalizer::get_real_client_ip();
		if ( '0.0.0.0' !== $ip ) {
			$order->update_meta_data( '_capiflow_client_ip', $ip );
		}

		$ua = Data_Normalizer::get_user_agent();
		if ( ! empty( $ua ) ) {
			$order->update_meta_data( '_capiflow_user_agent', $ua );
		}

		$cookies = Cookie_Manager::get_cookie_data();
		if ( ! empty( $cookies['fbc'] ) ) {
			$order->update_meta_data( '_capiflow_fbc', $cookies['fbc'] );
		}
		if ( ! empty( $cookies['fbp'] ) ) {
			$order->update_meta_data( '_capiflow_fbp', $cookies['fbp'] );
		}

		Cookie_Manager::get_external_id_for_order( $order );
		$order->update_meta_data( '_capiflow_traffic_source', $this->detect_traffic_source() );
		$order->save_meta_data();
	}

	/**
	 * Detect traffic source from UTM params and referrer.
	 *
	 * Priority: fbclid → UTM source → direct.
	 * Stored in order meta for Pro analytics segmentation.
	 *
	 * @return string Traffic source slug.
	 */
	private function detect_traffic_source(): string {
		$traffic_source = 'direct';
		$referer        = wp_get_referer() ?: '';

		// Check URL params for UTM / click IDs.
		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		$params = array_map( 'sanitize_text_field', wp_unslash( $_GET ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		// phpcs:enable

		if ( ! empty( $params['fbclid'] ) ) {
			$traffic_source = 'facebook_ads';
		} elseif ( ! empty( $params['utm_source'] ) ) {
			$traffic_source = sanitize_text_field( $params['utm_source'] );
		} elseif ( ! empty( $referer ) ) {
			$ref_host = wp_parse_url( $referer, PHP_URL_HOST ) ?: '';

			if ( strpos( $ref_host, 'facebook' ) !== false ) {
				$traffic_source = 'facebook';
			} elseif ( strpos( $ref_host, 'google' ) !== false ) {
				$traffic_source = 'google';
			} elseif ( ! empty( $ref_host ) ) {
				// Check referrer UTM params.
				$ref_query = wp_parse_url( $referer, PHP_URL_QUERY ) ?: '';
				if ( $ref_query ) {
					parse_str( $ref_query, $ref_params );
					if ( ! empty( $ref_params['utm_source'] ) ) {
						$traffic_source = sanitize_text_field( $ref_params['utm_source'] );
					}
				}
			}
		}

		return $traffic_source;
	}
}
