<?php
/**
 * Public-facing tracking integration.
 *
 * @package Live_Traffic_Analytics
 */

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

/**
 * Handles front-end tracking script and REST endpoint.
 */
class WPLTA_Public {

	/**
	 * Singleton instance.
	 *
	 * @var WPLTA_Public|null
	 */
	private static $instance = null;

	/**
	 * Get instance.
	 *
	 * @return WPLTA_Public
	 */
	public static function get_instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}

		return self::$instance;
	}

	/**
	 * Register hooks.
	 */
	private function __construct() {
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_tracking_assets' ) );
		add_action( 'rest_api_init', array( $this, 'register_rest_routes' ) );
		add_shortcode( 'wplta_active_users', array( $this, 'render_active_users_shortcode' ) );
	}

	/**
	 * Enqueue tracking script on the front-end.
	 *
	 * @return void
	 */
	public function enqueue_tracking_assets() {
		if ( is_admin() || is_feed() || is_robots() || is_trackback() ) {
			return;
		}

		if ( ! apply_filters( 'wplta_should_track_request', $this->is_trackable_request() ) ) {
			return;
		}

		wp_enqueue_script(
			'wplta-public-tracker',
			WPLTA_PLUGIN_URL . 'public/js/wplta-tracker.js',
			array(),
			WPLTA_VERSION,
			true
		);

		wp_localize_script(
			'wplta-public-tracker',
			'wpltaPublic',
			array(
				'restUrl'        => esc_url_raw( rest_url( 'wplta/v1/track' ) ),
				'nonce'          => wp_create_nonce( 'wp_rest' ),
				'heartbeatMs'    => WPLTA_Settings::get_tracking_heartbeat_ms(),
				'sessionTtlMs'   => 30 * MINUTE_IN_SECONDS * 1000,
				'isUserLoggedIn' => is_user_logged_in(),
			)
		);
	}

	/**
	 * Register tracking endpoint.
	 *
	 * @return void
	 */
	public function register_rest_routes() {
		register_rest_route(
			'wplta/v1',
			'/track',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'handle_tracking_request' ),
				'permission_callback' => array( $this, 'validate_public_request' ),
				'args'                => array(
					'session_id'   => array( 'required' => true, 'type' => 'string' ),
					'page_view_id' => array( 'required' => true, 'type' => 'string' ),
					'page_url'     => array( 'required' => true, 'type' => 'string' ),
				),
			)
		);
	}

	/**
	 * Validate the public request nonce.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return true|WP_Error
	 */
	public function validate_public_request( $request ) {
		if ( WPLTA_Helpers::verify_rest_nonce( $request ) ) {
			if ( ! WPLTA_Helpers::is_same_site_request( $request ) ) {
				return new WP_Error(
					'wplta_invalid_origin',
					__( 'Invalid tracking origin.', 'live-traffic-analytics' ),
					array( 'status' => 403 )
				);
			}

			if ( $this->is_rate_limited( $request ) ) {
				return new WP_Error(
					'wplta_rate_limited',
					__( 'Tracking request rate limit exceeded.', 'live-traffic-analytics' ),
					array( 'status' => 429 )
				);
			}

			return true;
		}

		return new WP_Error(
			'wplta_invalid_nonce',
			__( 'Invalid tracking nonce.', 'live-traffic-analytics' ),
			array( 'status' => 403 )
		);
	}

	/**
	 * Persist activity data.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function handle_tracking_request( $request ) {
		$payload = WPLTA_Helpers::sanitize_tracking_payload( $request->get_json_params() );

		if ( empty( $payload['session_id'] ) || empty( $payload['page_view_id'] ) || empty( $payload['page_url'] ) ) {
			return new WP_Error(
				'wplta_missing_data',
				__( 'Required tracking fields are missing.', 'live-traffic-analytics' ),
				array( 'status' => 400 )
			);
		}

		$user_agent = ! empty( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : '';
		$ip_address = WPLTA_Helpers::get_client_ip();
		$geo_data   = WPLTA_Helpers::get_geo_data_by_ip( $ip_address );
		$signals    = WPLTA_Repository::get_recent_ip_signals( $ip_address, 10 );
		$bot_data   = WPLTA_Helpers::detect_bot( $user_agent, $payload, $signals );
		$context    = array(
			'ip_address'  => $ip_address ? $ip_address : 'Unknown',
			'country'     => $geo_data['country'],
			'latitude'    => $geo_data['latitude'],
			'longitude'   => $geo_data['longitude'],
			'user_agent'  => $user_agent,
			'browser'     => WPLTA_Helpers::detect_browser( $user_agent ),
			'device_type' => WPLTA_Helpers::detect_device_type( $user_agent ),
			'is_bot'      => ! empty( $bot_data['is_bot'] ),
			'bot_name'    => ! empty( $bot_data['bot_name'] ) ? $bot_data['bot_name'] : '',
		);

		$result = WPLTA_Repository::save_tracking_event( $payload, $context );

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

	/**
	 * Check if current request should be tracked.
	 *
	 * @return bool
	 */
	private function is_trackable_request() {
		if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
			return false;
		}

		if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
			return false;
		}

		if ( is_user_logged_in() && current_user_can( 'manage_options' ) ) {
			return false;
		}

		return true;
	}

	/**
	 * Apply a lightweight per-IP request throttle to reduce analytics spam.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return bool
	 */
	private function is_rate_limited( $request ) {
		$ip_address = WPLTA_Helpers::get_client_ip();
		$payload    = $request->get_json_params();
		$session_id = ! empty( $payload['session_id'] ) ? sanitize_text_field( wp_unslash( $payload['session_id'] ) ) : 'guest';
		$page_view  = ! empty( $payload['page_view_id'] ) ? sanitize_text_field( wp_unslash( $payload['page_view_id'] ) ) : 'page';
		$bucket_key = 'wplta_rate_' . md5( $ip_address . '|' . $session_id . '|' . $page_view );
		$hits       = (int) get_transient( $bucket_key );

		if ( $hits >= 40 ) {
			return true;
		}

		set_transient( $bucket_key, $hits + 1, MINUTE_IN_SECONDS );

		return false;
	}

	/**
	 * Render active users count for future front-end expansion.
	 *
	 * @return string
	 */
	public function render_active_users_shortcode() {
		return esc_html( (string) WPLTA_Repository::get_active_users_count() );
	}
}
