<?php
// Streams Audio back from OpenAI TTS service using WP_Http with streaming

//if ( ! defined( 'ABSPATH' ) ) exit; // Cannot place this here as it breaks javascript client code. Nonce check is performed below to prevent unauth access

header('Content-Type: audio/mpeg');

require_once './includes/twx_util.php';

TWXChatUtil::loadWordpress();

// Raw input
$input_raw = file_get_contents('php://input');
$input_sanitized = wp_kses_post( wp_unslash( $input_raw ) ); // sanitize raw string
if (!TWXChatUtil::isValidJson($input_sanitized)) {
    wp_send_json_error('Invalid input', 403);
    wp_die();
}
$input = json_decode($input_sanitized, true);

// Nonce validation to ensure valid Plugin Browser session
$nonce = isset($input['nonce']) ? sanitize_text_field(wp_unslash($input['nonce'])) : '';
if (!wp_verify_nonce($nonce, 'twx_chat_nonce')) {
    wp_send_json_error('Invalid nonce', 403);
    wp_die();
}

// Sanitization
$text  = sanitize_text_field($input['text'] ?? '');
if (empty($text)) {
    wp_send_json_error('Empty text', 403);
    wp_die();
}

$voice = sanitize_text_field($input['voice'] ?? 'nova');

$model = 'tts-1';

$apiKey = get_option('twx_chat_options')['openai_apikey'] ?? '';

$openaiUrl = 'https://api.openai.com/v1/audio/speech';
$body = [
    'model'           => $model,
    'voice'           => $voice,
    'input'           => $text,
    'response_format' => 'mp3',
];

$fullStreamOutput = '';

// Attach curl streaming handler
add_action('http_api_curl', function($handle) use (&$fullStreamOutput) {
    curl_setopt($handle, CURLOPT_WRITEFUNCTION, function($ch, $data) use (&$fullStreamOutput) {
        // Output raw audio as it's received
        echo $data;
        $fullStreamOutput .= $data;
        // Flush immediately for real-time playback
        flush();
        return strlen($data);
    });
    curl_setopt($handle, CURLOPT_TIMEOUT, 0); // keep alive for streaming
});

$http = new WP_Http();
$response = $http->request($openaiUrl, [
    'method'  => 'POST',
    'headers' => [
        'Authorization' => 'Bearer ' . $apiKey,
        'Content-Type'  => 'application/json',
    ],
    'body'    => wp_json_encode($body),
    'timeout' => 0, // allow long-running stream
]);

// Clean up curl hook
remove_all_actions('http_api_curl');

// Error handling
if (is_wp_error($response)) {
    wp_send_json_error($response->get_error_message(), 500);
    wp_die();
}

exit; // Important: stop WP from appending extra output

?>