//! Voicemail session — answer → play greeting → beep → record → done.

use crate::audio_player::{play_beep, play_wav_file};
use crate::ipc::{emit_event, OutTx};
use crate::recorder::Recorder;
use std::net::SocketAddr;
use std::sync::Arc;
use tokio::net::UdpSocket;

/// Run a voicemail session on an RTP port.
///
/// 1. Plays the greeting WAV file to the caller
/// 2. Plays a beep tone
/// 3. Records the caller's message until BYE or max duration
///
/// The RTP receive loop is separate — it feeds packets to the recorder
/// via the returned channel.
pub async fn run_voicemail_session(
    rtp_socket: Arc<UdpSocket>,
    provider_media: SocketAddr,
    codec_pt: u8,
    voicebox_id: Option<String>,
    greeting_wav: Option<String>,
    recording_path: String,
    max_recording_ms: u64,
    call_id: String,
    caller_number: String,
    out_tx: OutTx,
) {
    let ssrc: u32 = rand::random();

    emit_event(
        &out_tx,
        "voicemail_started",
        serde_json::json!({
            "call_id": call_id,
            "voicebox_id": voicebox_id,
            "caller_number": caller_number,
        }),
    );

    // Step 1: Play greeting.
    let mut next_seq: u16 = 0;
    let mut next_ts: u32 = 0;

    if let Some(wav_path) = &greeting_wav {
        match play_wav_file(wav_path, rtp_socket.clone(), provider_media, codec_pt, ssrc).await {
            Ok(frames) => {
                next_seq = frames as u16;
                next_ts = frames * crate::rtp::rtp_clock_increment(codec_pt);
            }
            Err(e) => {
                emit_event(
                    &out_tx,
                    "voicemail_error",
                    serde_json::json!({ "call_id": call_id, "error": format!("greeting: {e}") }),
                );
            }
        }
    }

    // Step 2: Play beep (1kHz, 500ms).
    match play_beep(
        rtp_socket.clone(),
        provider_media,
        codec_pt,
        ssrc,
        next_seq,
        next_ts,
        1000,
        500,
    )
    .await
    {
        Ok((_seq, _ts)) => {}
        Err(e) => {
            emit_event(
                &out_tx,
                "voicemail_error",
                serde_json::json!({ "call_id": call_id, "error": format!("beep: {e}") }),
            );
        }
    }

    // Step 3: Record incoming audio.
    let recorder = match Recorder::new(&recording_path, codec_pt, Some(max_recording_ms)) {
        Ok(r) => r,
        Err(e) => {
            emit_event(
                &out_tx,
                "voicemail_error",
                serde_json::json!({ "call_id": call_id, "error": format!("recorder: {e}") }),
            );
            return;
        }
    };

    // Receive RTP and feed to recorder.
    let result = record_from_socket(rtp_socket, recorder, max_recording_ms).await;

    // Step 4: Done — emit recording result.
    emit_event(
        &out_tx,
        "recording_done",
        serde_json::json!({
            "call_id": call_id,
            "voicebox_id": voicebox_id,
            "file_path": result.file_path,
            "duration_ms": result.duration_ms,
            "caller_number": caller_number,
        }),
    );
}

/// Read RTP packets from the socket and feed them to the recorder.
/// Returns when the socket errors out (BYE closes the call/socket)
/// or max duration is reached.
async fn record_from_socket(
    socket: Arc<UdpSocket>,
    mut recorder: Recorder,
    max_ms: u64,
) -> crate::recorder::RecordingResult {
    let mut buf = vec![0u8; 65535];
    let deadline = tokio::time::Instant::now() + tokio::time::Duration::from_millis(max_ms + 2000);

    loop {
        let timeout = tokio::time::timeout_at(deadline, socket.recv_from(&mut buf));
        match timeout.await {
            Ok(Ok((n, _addr))) => {
                if !recorder.process_rtp(&buf[..n]) {
                    break; // Max duration reached.
                }
            }
            Ok(Err(_)) => break, // Socket error (closed).
            Err(_) => break,     // Timeout (max duration + grace).
        }
    }

    recorder.stop()
}
