//! Event types for the LiveSpeech SDK

use serde::{Deserialize, Serialize};

/// Disconnect reason
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DisconnectReason {
    /// Normal disconnection (client initiated)
    Normal,
    /// Error occurred
    Error,
    /// Connection timeout
    Timeout,
    /// Server closed connection
    ServerClose,
    /// Max reconnection attempts reached
    ReconnectFailed,
}

/// Error codes
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ErrorCode {
    ConnectionFailed,
    ConnectionTimeout,
    AuthenticationFailed,
    SessionError,
    AudioError,
    StreamingError,
    SttError,
    LlmError,
    TtsError,
    RateLimit,
    InternalError,
    InvalidMessage,
}

impl std::fmt::Display for ErrorCode {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let s = match self {
            ErrorCode::ConnectionFailed => "connection_failed",
            ErrorCode::ConnectionTimeout => "connection_timeout",
            ErrorCode::AuthenticationFailed => "authentication_failed",
            ErrorCode::SessionError => "session_error",
            ErrorCode::AudioError => "audio_error",
            ErrorCode::StreamingError => "streaming_error",
            ErrorCode::SttError => "stt_error",
            ErrorCode::LlmError => "llm_error",
            ErrorCode::TtsError => "tts_error",
            ErrorCode::RateLimit => "rate_limit",
            ErrorCode::InternalError => "internal_error",
            ErrorCode::InvalidMessage => "invalid_message",
        };
        write!(f, "{}", s)
    }
}

/// Connected event
#[derive(Debug, Clone)]
pub struct ConnectedEvent {
    pub connection_id: String,
    pub timestamp: String,
}

/// Disconnected event
#[derive(Debug, Clone)]
pub struct DisconnectedEvent {
    pub reason: DisconnectReason,
    pub code: Option<u16>,
    pub timestamp: String,
}

/// Session started event
#[derive(Debug, Clone)]
pub struct SessionStartedEvent {
    pub session_id: String,
    pub timestamp: String,
}

/// Session ended event
#[derive(Debug, Clone)]
pub struct SessionEndedEvent {
    pub session_id: String,
    pub timestamp: String,
}

/// Ready event
/// Indicates the session is ready for audio input
#[derive(Debug, Clone)]
pub struct ReadyEvent {
    pub timestamp: String,
}

/// User transcript event (user's speech transcription)
#[derive(Debug, Clone)]
pub struct UserTranscriptEvent {
    pub text: String,
    pub timestamp: String,
}

/// Response event (LLM response)
#[derive(Debug, Clone)]
pub struct ResponseEvent {
    pub text: String,
    pub is_final: bool,
    pub timestamp: String,
}

/// Audio event (TTS audio chunk)
#[derive(Debug, Clone)]
pub struct AudioEvent {
    pub data: Vec<u8>,
    pub format: String,
    pub sample_rate: u32,
    pub timestamp: String,
}

/// Error event
#[derive(Debug, Clone)]
pub struct ErrorEvent {
    pub code: ErrorCode,
    pub message: String,
    pub details: Option<String>,
    pub timestamp: String,
}

/// Reconnecting event
#[derive(Debug, Clone)]
pub struct ReconnectingEvent {
    pub attempt: u32,
    pub max_attempts: u32,
    pub delay_ms: u64,
    pub timestamp: String,
}

/// Turn complete event
/// Indicates the AI has finished its response turn
#[derive(Debug, Clone)]
pub struct TurnCompleteEvent {
    pub timestamp: String,
}

/// Streaming started event
#[derive(Debug, Clone)]
pub struct StreamingStartedEvent {
    pub timestamp: String,
}

/// Speech start event
#[derive(Debug, Clone)]
pub struct SpeechStartEvent {
    pub timestamp: String,
}

/// Speech end event
#[derive(Debug, Clone)]
pub struct SpeechEndEvent {
    pub timestamp: String,
}

/// Transcript event (user's speech transcription with details)
#[derive(Debug, Clone)]
pub struct TranscriptEvent {
    pub text: String,
    pub is_final: bool,
    pub confidence: Option<f32>,
    pub timestamp: String,
}

/// LiveSpeech event enum
#[derive(Debug, Clone)]
pub enum LiveSpeechEvent {
    Connected(ConnectedEvent),
    Disconnected(DisconnectedEvent),
    Reconnecting(ReconnectingEvent),
    SessionStarted(SessionStartedEvent),
    SessionEnded(SessionEndedEvent),
    Ready(ReadyEvent),
    UserTranscript(UserTranscriptEvent),
    Transcript(TranscriptEvent),
    StreamingStarted(StreamingStartedEvent),
    SpeechStart(SpeechStartEvent),
    SpeechEnd(SpeechEndEvent),
    Response(ResponseEvent),
    Audio(AudioEvent),
    TurnComplete(TurnCompleteEvent),
    Error(ErrorEvent),
}

/// Type alias for user transcript handler
pub type UserTranscriptHandler = Box<dyn Fn(&str) + Send + Sync>;

/// Type alias for transcript handler (with is_final parameter)
pub type TranscriptHandler = Box<dyn Fn(&str, bool) + Send + Sync>;

/// Type alias for response handler
pub type ResponseHandler = Box<dyn Fn(&str, bool) + Send + Sync>;

/// Type alias for audio handler
pub type AudioHandler = Box<dyn Fn(&[u8]) + Send + Sync>;

/// Type alias for error handler
pub type ErrorHandler = Box<dyn Fn(&ErrorEvent) + Send + Sync>;
