<?php

/**
 * Central dispatcher for custom events sent from the browser.
 *
 * For now this focuses on sending Facebook Conversions API events that are
 * deduplicated with the browser Pixel using event_id.
 */
class WPCode_Pixel_Events {

	/**
	 * Constructor.
	 */
	public function __construct() {
		add_action( 'rest_api_init', array( $this, 'register_routes' ) );
	}

	/**
	 * Register the REST API routes used for tracking custom events.
	 *
	 * @return void
	 */
	public function register_routes() {
		register_rest_route(
			'wpcode-pixel/v1',
			'/track-event',
			array(
				'methods'             => 'POST',
				'callback'            => array( $this, 'rest_track_event' ),
				'permission_callback' => '__return_true',
				'args'                => array(),
			)
		);
	}

	/**
	 * REST callback to track a custom event.
	 *
	 * @param WP_REST_Request $request The REST request.
	 *
	 * @return WP_REST_Response|WP_Error
	 */
	public function rest_track_event( WP_REST_Request $request ) {
		$params = $request->get_json_params();

		$event_name = isset( $params['event_name'] ) ? sanitize_text_field( $params['event_name'] ) : '';
		$event_id   = isset( $params['event_id'] ) ? sanitize_text_field( $params['event_id'] ) : '';
		$value      = isset( $params['value'] ) ? floatval( $params['value'] ) : 0;
		$url        = isset( $params['url'] ) ? esc_url_raw( $params['url'] ) : '';
		$platforms  = array();

		if ( isset( $params['platforms'] ) && is_array( $params['platforms'] ) ) {
			$platforms = array_map( 'sanitize_key', $params['platforms'] );
		}

		if ( '' === $event_name || '' === $event_id ) {
			return new WP_Error(
				'wpcode_pixel_invalid_event',
				__( 'Missing event_name or event_id for custom event.', 'wpcode-pixel' ),
				array( 'status' => 400 )
			);
		}

		$has_facebook  = in_array( 'facebook', $platforms, true );
		$has_pinterest = in_array( 'pinterest', $platforms, true );
		$has_tiktok    = in_array( 'tiktok', $platforms, true );
		$has_snapchat  = in_array( 'snapchat', $platforms, true );

		// If none of the supported platforms are present, bail early.
		if ( ! $has_facebook && ! $has_pinterest && ! $has_tiktok && ! $has_snapchat ) {
			return rest_ensure_response(
				array(
					'success' => true,
				)
			);
		}

		// Facebook server event.
		if ( $has_facebook ) {
			$this->track_facebook_event(
				array(
					'event_name' => $event_name,
					'event_id'   => $event_id,
					'value'      => $value,
					'url'        => $url,
				)
			);
		}

		// Pinterest server event.
		if ( $has_pinterest ) {
			$this->track_pinterest_event(
				array(
					'event_name' => $event_name,
					'event_id'   => $event_id,
					'value'      => $value,
					'url'        => $url,
				)
			);
		}

		// TikTok server event.
		if ( $has_tiktok ) {
			$this->track_tiktok_event(
				array(
					'event_name' => $event_name,
					'event_id'   => $event_id,
					'value'      => $value,
					'url'        => $url,
				)
			);
		}

		// Snapchat server event.
		if ( $has_snapchat ) {
			$this->track_snapchat_event(
				array(
					'event_name' => $event_name,
					'event_id'   => $event_id,
					'value'      => $value,
					'url'        => $url,
				)
			);
		}

		return rest_ensure_response(
			array(
				'success' => true,
			)
		);
	}

	/**
	 * Track a custom event via Facebook Conversions API.
	 *
	 * @param array $event_data Normalized event data.
	 *
	 * @return void
	 */
	public function track_facebook_event( $event_data ) {
		if ( empty( $event_data['event_name'] ) || empty( $event_data['event_id'] ) ) {
			return;
		}

		// Find the Facebook auto-insert type.
		if ( empty( wpcode_pixel()->auto_insert ) || empty( wpcode_pixel()->auto_insert->types ) ) {
			return;
		}

		$facebook_type = null;
		foreach ( wpcode_pixel()->auto_insert->types as $type ) {
			if ( isset( $type->type ) && 'facebook' === $type->type ) {
				$facebook_type = $type;
				break;
			}
		}

		if ( ! $facebook_type || ! method_exists( $facebook_type, 'has_api_token' ) || ! $facebook_type->has_api_token() ) {
			// No Conversions API token configured – nothing to send server-side.
			return;
		}

		$server_event = array(
			'event_name'       => $event_data['event_name'],
			'event_time'       => time(),
			'event_id'         => $event_data['event_id'],
			'event_source_url' => ! empty( $event_data['url'] ) ? esc_url_raw( $event_data['url'] ) : home_url( add_query_arg( array(), '/' ) ),
		);

		$value = isset( $event_data['value'] ) ? floatval( $event_data['value'] ) : 0;
		if ( $value > 0 ) {
			$server_event['custom_data'] = array(
				'value' => $value,
			);
		}

		// Build user_data using the existing helper to ensure proper hashing & cookies (fbp/fbc).
		$user_ip    = function_exists( 'wpcode_get_user_ip' ) ? wpcode_get_user_ip() : '';
		$user_agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : '';
		$user_id    = is_user_logged_in() ? get_current_user_id() : 0;
		$email      = '';

		if ( $user_id ) {
			$user = get_userdata( $user_id );
			if ( $user && ! empty( $user->user_email ) ) {
				$email = $user->user_email;
			}
		}

		if ( method_exists( $facebook_type, 'get_user_data' ) ) {
			$server_event['user_data'] = $facebook_type->get_user_data(
				array(
					'user_ip'    => $user_ip,
					'user_agent' => $user_agent,
					'user_id'    => $user_id,
					'email'      => $email,
				)
			);
		}

		// Send the event to all configured Facebook pixel/token pairs.
		if ( method_exists( $facebook_type, 'send_server_event' ) ) {
			$facebook_type->send_server_event( $server_event );
		}
	}

	/**
	 * Track a custom event via Pinterest Conversions API.
	 *
	 * @param array $event_data Normalized event data.
	 *
	 * @return void
	 */
	public function track_pinterest_event( $event_data ) {
		if ( empty( $event_data['event_name'] ) ) {
			return;
		}

		// Find the Pinterest auto-insert type.
		if ( empty( wpcode_pixel()->auto_insert ) || empty( wpcode_pixel()->auto_insert->types ) ) {
			return;
		}

		$pinterest_type = null;
		foreach ( wpcode_pixel()->auto_insert->types as $type ) {
			if ( isset( $type->type ) && 'pinterest' === $type->type ) {
				$pinterest_type = $type;
				break;
			}
		}

		if ( ! $pinterest_type || ! method_exists( $pinterest_type, 'has_api_token' ) || ! $pinterest_type->has_api_token() ) {
			// No API token / ad account configured – nothing to send server-side.
			return;
		}

		// Normalize the event name to one of Pinterest's documented standard names
		// when possible, otherwise fall back to "Custom" to avoid "UNKNOWN" labels.
		$raw_event_name = $event_data['event_name'];

		$allowed_event_names = array(
			// Common Pinterest standard events (various casings that users might enter).
			'PageVisit',
			'ViewCategory',
			'Search',
			'AddToCart',
			'Checkout',
			'WatchVideo',
			'Lead',
			'Signup',
			'Custom',
			'pagevisit',
			'viewcategory',
			'search',
			'addtocart',
			'checkout',
			'watchvideo',
			'lead',
			'signup',
			'custom',
		);

		if ( in_array( $raw_event_name, $allowed_event_names, true ) ) {
			$event_name = $raw_event_name;
		} else {
			$event_name = 'Custom';
		}

		$server_event = array(
			'event_name'       => $event_name,
			'event_time'       => time(),
			'event_source_url' => ! empty( $event_data['url'] ) ? esc_url_raw( $event_data['url'] ) : home_url( add_query_arg( array(), '/' ) ),
			'action_source'    => 'web',
		);

		// Optional event_id for diagnostics / dedup, if provided.
		if ( ! empty( $event_data['event_id'] ) ) {
			$server_event['event_id'] = $event_data['event_id'];
		}

		$value = isset( $event_data['value'] ) ? floatval( $event_data['value'] ) : 0;
		if ( $value > 0 ) {
			$server_event['custom_data']['value'] = (string) $value;
		}

		// Build user_data using the existing helper to ensure proper hashing & attribution.
		$user_ip    = function_exists( 'wpcode_get_user_ip' ) ? wpcode_get_user_ip() : '';
		$user_agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : '';
		$user_id    = is_user_logged_in() ? get_current_user_id() : 0;
		$email      = '';

		if ( $user_id ) {
			$user = get_userdata( $user_id );
			if ( $user && ! empty( $user->user_email ) ) {
				$email = $user->user_email;
			}
		}

		if ( method_exists( $pinterest_type, 'get_user_data' ) ) {
			$server_event['user_data'] = $pinterest_type->get_user_data(
				array(
					'user_ip'    => $user_ip,
					'user_agent' => $user_agent,
					'user_id'    => $user_id,
					'email'      => $email,
				)
			);
		}

		if ( method_exists( $pinterest_type, 'send_server_event' ) ) {
			$pinterest_type->send_server_event( $server_event );
		}
	}

	/**
	 * Track a custom event via TikTok Events API.
	 *
	 * @param array $event_data Normalized event data.
	 *
	 * @return void
	 */
	public function track_tiktok_event( $event_data ) {
		if ( empty( $event_data['event_name'] ) ) {
			return;
		}

		// Find the TikTok auto-insert type.
		if ( empty( wpcode_pixel()->auto_insert ) || empty( wpcode_pixel()->auto_insert->types ) ) {
			return;
		}

		$tiktok_type = null;
		foreach ( wpcode_pixel()->auto_insert->types as $type ) {
			if ( isset( $type->type ) && 'tiktok' === $type->type ) {
				$tiktok_type = $type;
				break;
			}
		}

		if ( ! $tiktok_type || ! method_exists( $tiktok_type, 'has_api_token' ) || ! $tiktok_type->has_api_token() ) {
			// No access token configured – nothing to send server-side.
			return;
		}

		$url = ! empty( $event_data['url'] ) ? esc_url_raw( $event_data['url'] ) : home_url( add_query_arg( array(), '/' ) );

		$event = array(
			'event'      => $event_data['event_name'],
			'timestamp'  => date_i18n( 'c' ),
			'context'    => array(
				'page'       => array(
					'url' => $url,
				),
				'ip'         => '',
				'user_agent' => '',
			),
			'properties' => array(),
		);

		// Preserve the browser-generated event id for deduplication when available.
		if ( ! empty( $event_data['event_id'] ) ) {
			$event['event_id'] = $event_data['event_id'];
		}

		$value = isset( $event_data['value'] ) ? floatval( $event_data['value'] ) : 0;
		if ( $value > 0 ) {
			$event['properties']['value'] = $value;
		}

		// Attach click identifiers & basic user data similar to ecommerce events.
		$user_ip    = function_exists( 'wpcode_get_user_ip' ) ? wpcode_get_user_ip() : '';
		$user_agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : '';
		$user_id    = is_user_logged_in() ? get_current_user_id() : 0;
		$email      = '';

		if ( $user_id ) {
			$user = get_userdata( $user_id );
			if ( $user && ! empty( $user->user_email ) ) {
				$email = $user->user_email;
			}
		}

		$event['context']['ip']         = $user_ip;
		$event['context']['user_agent'] = $user_agent;

		// Add TikTok click id when available.
		if ( method_exists( $tiktok_type, 'get_ttclid' ) ) {
			$ttclid = $tiktok_type->get_ttclid();
			if ( ! empty( $ttclid ) ) {
				$event['context']['ad'] = array(
					'callback' => $ttclid,
				);
			}
		}

		// Attach user data in the TikTok-specific format.
		if ( method_exists( $tiktok_type, 'get_user_data' ) ) {
			$event['context']['user'] = $tiktok_type->get_user_data(
				array(
					'user_ip'    => $user_ip,
					'user_agent' => $user_agent,
					'user_id'    => $user_id,
					'email'      => $email,
				)
			);
		}

		if ( method_exists( $tiktok_type, 'send_server_event' ) ) {
			$tiktok_type->send_server_event( $event );
		}
	}

	/**
	 * Track a custom event via Snapchat Conversions API.
	 *
	 * @param array $event_data Normalized event data.
	 *
	 * @return void
	 */
	public function track_snapchat_event( $event_data ) {
		if ( empty( $event_data['event_name'] ) ) {
			return;
		}

		// Find the Snapchat auto-insert type.
		if ( empty( wpcode_pixel()->auto_insert ) || empty( wpcode_pixel()->auto_insert->types ) ) {
			return;
		}

		$snapchat_type = null;
		foreach ( wpcode_pixel()->auto_insert->types as $type ) {
			if ( isset( $type->type ) && 'snapchat' === $type->type ) {
				$snapchat_type = $type;
				break;
			}
		}

		if ( ! $snapchat_type || ! method_exists( $snapchat_type, 'has_api_token' ) || ! $snapchat_type->has_api_token() ) {
			// No API token configured – nothing to send server-side.
			return;
		}

		$event = array(
			'event_type' => $event_data['event_name'],
		);

		$value = isset( $event_data['value'] ) ? floatval( $event_data['value'] ) : 0;
		if ( $value > 0 ) {
			$event['price'] = $value;
		}

		// Attach basic user data in the Snapchat-specific format.
		$user_ip    = function_exists( 'wpcode_get_user_ip' ) ? wpcode_get_user_ip() : '';
		$user_agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : '';
		$user_id    = is_user_logged_in() ? get_current_user_id() : 0;
		$email      = '';

		if ( $user_id ) {
			$user = get_userdata( $user_id );
			if ( $user && ! empty( $user->user_email ) ) {
				$email = $user->user_email;
			}
		}

		if ( method_exists( $snapchat_type, 'get_user_data' ) ) {
			$event = array_merge(
				$event,
				$snapchat_type->get_user_data(
					array(
						'user_ip'    => $user_ip,
						'user_agent' => $user_agent,
						'user_id'    => $user_id,
						'email'      => $email,
					)
				)
			);
		}

		if ( method_exists( $snapchat_type, 'send_server_event' ) ) {
			$snapchat_type->send_server_event( $event );
		}
	}
}
