<?php
/**
 * WebRTC session AJAX handler module for SiteStaffr widget.
 *
 * @package SiteStaffr
 */

class SiteStaffr_Widget_WebRTC_Session_Handler {

	/**
	 * AJAX handler for WebRTC SDP exchange.
	 *
	 * Proxies SDP offer/answer to middleware with HMAC authentication.
	 * Browser cannot call middleware directly due to HMAC signature requirement.
	 *
	 * @since 0.13.22
	 * @param SiteStaffr_Widget $widget Widget instance.
	 * @param string           $ip_address Client IP address.
	 * @param callable         $get_api_secret Callback returning API secret.
	 * @param callable         $get_realtime_custom_instructions Callback returning custom instructions.
	 * @param callable         $enrich_realtime_business_info Callback enriching business info payload.
	 * @return void
	 */
	public static function ajax_webrtc_session( SiteStaffr_Widget $widget, $ip_address, callable $get_api_secret, callable $get_realtime_custom_instructions, callable $enrich_realtime_business_info ) {
		check_ajax_referer( 'sitestaffr_webrtc_session', 'nonce' );

		// Additional security guards: honeypot, ban, per-IP rate limit.
		SiteStaffr_Public_Request_Guards::enforce_public_guards( array(
			'nonce_action' => 'sitestaffr_webrtc_session',
			'ip'           => $ip_address,
			'honeypot'     => true,
			'ban_check'    => true,
			'rate_limit'   => 20,
		) );

		// Get API secret for HMAC signature (per-site or global)
		$preflight_config = SiteStaffr_Public_Middleware_Client::get_public_preflight_config( $get_api_secret() );
		$api_secret = $preflight_config['api_secret'];
		if ( $preflight_config['missing_api_secret'] ) {
			SiteStaffr_Logger::legacy( SiteStaffr_Public_Middleware_Client::log_prefix_webrtc_sdp_ajax() . SiteStaffr_Public_Middleware_Client::log_suffix_missing_api_secret() );
			wp_send_json_error( array(
				'message' => SiteStaffr_Public_Middleware_Client::msg_config_missing_api_secret(),
			), SiteStaffr_Public_Middleware_Client::http_500() );
			return;
		}

		// Get site token from POST
		$site_token = SiteStaffr_Public_Request_Guards::get_post_text_field( 'site_token' );
		if ( empty( $site_token ) ) {
			SiteStaffr_Logger::legacy( SiteStaffr_Public_Middleware_Client::log_prefix_webrtc_sdp_ajax() . SiteStaffr_Public_Middleware_Client::log_suffix_missing_site_token_in_request() );
			wp_send_json_error( array(
				'message' => SiteStaffr_Public_Middleware_Client::msg_missing_site_token(),
			), 400 );
			return;
		}
		$account_id = sanitize_text_field( get_option( 'sitestaffr_account_id', '' ) );
		$installation_id = sanitize_text_field( get_option( 'sitestaffr_installation_id', '' ) );

		// Get SDP offer from POST (sanitized via sanitize_textarea_field in request guards).
		$sdp_offer = SiteStaffr_Public_Request_Guards::get_post_raw_field( 'sdp' );
		if ( empty( $sdp_offer ) ) {
			SiteStaffr_Logger::legacy( SiteStaffr_Public_Middleware_Client::log_prefix_webrtc_sdp_ajax() . 'Missing SDP offer in request' );
			wp_send_json_error( array(
				'message' => SiteStaffr_Public_Middleware_Client::msg_missing_sdp_offer(),
			), 400 );
			return;
		}

		// Basic SDP format validation (all SDP starts with "v=0")
		if ( strpos( $sdp_offer, 'v=0' ) !== 0 ) {
			wp_send_json_error( array( 'message' => SiteStaffr_Public_Middleware_Client::msg_invalid_sdp_format() ), 400 );
			return;
		}

		// Size limit (prevent DoS)
		if ( strlen( $sdp_offer ) > 50000 ) {
			wp_send_json_error( array( 'message' => SiteStaffr_Public_Middleware_Client::msg_sdp_offer_too_large() ), 413 );
			return;
		}

		// Fetch business info to include in middleware request (eliminates callback)
		// This prevents the middleware from needing to call back to WordPress REST API
		$saved_settings = get_option( 'sitestaffr_settings', array() );
		$widget_settings = SiteStaffr_Widget_Settings_Provider::get_widget_settings();
		$business_info = array(
			'business_name'        => isset( $saved_settings['business_name'] ) ? $saved_settings['business_name'] : '',
			'business_description' => isset( $saved_settings['business_context'] ) ? $saved_settings['business_context'] : get_option( 'sitestaffr_business_description', '' ),
			'business_hours'       => isset( $saved_settings['business_hours'] ) ? $saved_settings['business_hours'] : get_option( 'sitestaffr_business_hours', '' ),
			'business_phone'       => isset( $saved_settings['business_phone'] ) ? $saved_settings['business_phone'] : get_option( 'sitestaffr_business_phone', '' ),
			'custom_greeting'      => isset( $saved_settings['custom_greeting'] ) ? sanitize_text_field( $saved_settings['custom_greeting'] ) : '',
			'custom_greeting_tone' => isset( $saved_settings['custom_greeting_tone'] ) ? sanitize_key( $saved_settings['custom_greeting_tone'] ) : 'warm_neutral',
			'custom_instructions'       => $get_realtime_custom_instructions( $saved_settings ),
			'custom_instructions_user'  => SiteStaffr_Business_Enrichment::get_user_custom_instructions(),
			'ai_voice'             => isset( $widget_settings['ai_voice'] ) ? $widget_settings['ai_voice'] : 'marin',
			'notification_email'       => ! empty( $saved_settings['notification_email'] ) ? $saved_settings['notification_email'] : get_option( 'admin_email' ),
			'collect_contact'          => isset( $saved_settings['ai_collect_contact'] ) ? (bool) $saved_settings['ai_collect_contact'] : true,
			'disregard_personal_info'  => isset( $saved_settings['ai_disregard_personal_info'] ) ? (bool) $saved_settings['ai_disregard_personal_info'] : false,
		);
		// Accept optional persona from shortcode (sanitize + allow-list for defense in depth)
		$persona_raw = SiteStaffr_Public_Request_Guards::get_post_text_field( 'persona' );
		$allowed_personas = array( 'default', 'onboarding', 'informational' );
		if ( ! empty( $persona_raw ) && in_array( $persona_raw, $allowed_personas, true ) ) {
			$business_info['persona'] = $persona_raw;
		}
		// Include page-specific knowledge context if available.
		$current_post_id = isset( $_POST['current_post_id'] ) ? absint( wp_unslash( $_POST['current_post_id'] ) ) : 0;
		$knowledge_mode  = isset( $saved_settings['knowledge_mode'] ) ? sanitize_key( $saved_settings['knowledge_mode'] ) : 'search';
		$chunks          = ( $current_post_id > 0 ) ? SiteStaffr_Knowledge_Manager::get_chunks_for_post( $current_post_id ) : array();
		if ( ! empty( $chunks ) ) {
			// Cap at 3 chunks for WebRTC to stay within HTTP header size limits (~8KB).
			$business_info['knowledge_context'] = array(
				'current_page'    => get_the_title( $current_post_id ),
				'current_post_id' => $current_post_id,
				'chunks'          => array_slice( $chunks, 0, 3 ),
				'mode'            => $knowledge_mode,
			);
		} elseif ( SiteStaffr_Knowledge_Manager::has_knowledge() ) {
			$business_info['knowledge_context'] = array(
				'current_page'    => ( $current_post_id > 0 ) ? get_the_title( $current_post_id ) : '',
				'current_post_id' => $current_post_id > 0 ? $current_post_id : null,
				'chunks'          => array(),
				'has_knowledge'   => true,
				'mode'            => $knowledge_mode,
			);
		}

		// Page Expert Mode: include site pages directory for navigation.
		if ( 'page_scoped' === $knowledge_mode ) {
			if ( empty( $business_info['knowledge_context'] ) ) {
				$business_info['knowledge_context'] = array(
					'mode'      => $knowledge_mode,
					'chunks'    => array(),
					'sitePages' => SiteStaffr_Knowledge_Manager::get_site_pages(),
				);
			} else {
				$business_info['knowledge_context']['sitePages'] = SiteStaffr_Knowledge_Manager::get_site_pages();
			}
		}
		$business_info = $enrich_realtime_business_info( $business_info );

		// Get middleware URL
		$middleware_url = $preflight_config['middleware_url'];
		if ( $preflight_config['missing_middleware_url'] ) {
			SiteStaffr_Logger::legacy( SiteStaffr_Public_Middleware_Client::log_prefix_webrtc_sdp_ajax() . SiteStaffr_Public_Middleware_Client::log_suffix_missing_middleware_url() );
			wp_send_json_error( array(
				'message' => SiteStaffr_Public_Middleware_Client::msg_config_missing_middleware_url(),
			), SiteStaffr_Public_Middleware_Client::http_500() );
			return;
		}

		$webrtc_operation = SiteStaffr_Public_Middleware_Client::webrtc_session_request(
			$middleware_url,
			$site_token,
			get_site_url(),
			$sdp_offer,
			$api_secret,
			$business_info,
			$ip_address,
			$account_id,
			$installation_id
		);

		if ( 'request_error' === $webrtc_operation['result'] ) {
			SiteStaffr_Logger::legacy( SiteStaffr_Public_Middleware_Client::log_prefix_webrtc_sdp_ajax() . SiteStaffr_Public_Middleware_Client::log_suffix_request_failed() . $webrtc_operation['error_message'] );
			wp_send_json_error( $webrtc_operation['error_payload'], $webrtc_operation['status_code'] );
			return;
		}

		if ( 'middleware_error' === $webrtc_operation['result'] ) {
			if ( '' !== $webrtc_operation['status_body_for_log'] ) {
				SiteStaffr_Logger::legacy( sprintf(
					SiteStaffr_Public_Middleware_Client::log_prefix_webrtc_sdp_ajax() . SiteStaffr_Public_Middleware_Client::log_fmt_middleware_returned_status_body(),
					$webrtc_operation['status_body_for_log']
				) );
			}
			wp_send_json_error( $webrtc_operation['error_payload'], $webrtc_operation['status_code'] );
			return;
		}

		if ( 'invalid_json' === $webrtc_operation['result'] ) {
			SiteStaffr_Logger::legacy( SiteStaffr_Public_Middleware_Client::log_prefix_webrtc_sdp_ajax() . SiteStaffr_Public_Middleware_Client::log_suffix_invalid_json_response_from_middleware() );
			wp_send_json_error( $webrtc_operation['error_payload'], $webrtc_operation['status_code'] );
			return;
		}

		if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
			SiteStaffr_Logger::legacy( sprintf(
				SiteStaffr_Public_Middleware_Client::log_prefix_webrtc_sdp_ajax() . 'Response received successfully for IP %s',
				$ip_address
			) );
		}

		// Return JSON with SDP and session configuration to browser
		wp_send_json_success( $webrtc_operation['success_payload'] );
	}
}
