//! Conversion between proto types and session_manager types.

use chrono::{DateTime, Utc};

use super::generated::admin::{OnlineStatus as ProtoStatus, UserSession as ProtoSession, SessionInfo as ProtoInfo};

use session_manager::{OnlineStatus, SessionInfo, UserSession};

/// Convert DateTime<Utc> → prost_types::Timestamp.
fn datetime_to_timestamp(dt: DateTime<Utc>) -> prost_types::Timestamp {
    prost_types::Timestamp {
        seconds: dt.timestamp(),
        nanos: dt.timestamp_subsec_nanos() as i32,
    }
}

/// Convert session_manager UserSession → proto UserSession.
pub fn to_proto_session(s: &UserSession) -> ProtoSession {
    ProtoSession {
        session_id: s.session_id.to_string(),
        user_id: s.user_id.to_string(),
        workspace_id: s.workspace_id.to_string(),
        ip_address: s.ip_address.clone(),
        user_agent: s.user_agent.clone(),
        connected_at: Some(datetime_to_timestamp(s.connected_at)),
        last_heartbeat: Some(datetime_to_timestamp(s.last_heartbeat)),
    }
}

/// Convert session_manager OnlineStatus → proto OnlineStatus.
pub fn to_proto_status(s: OnlineStatus) -> ProtoStatus {
    match s {
        OnlineStatus::Online => ProtoStatus::Online,
        OnlineStatus::Idle => ProtoStatus::Idle,
        OnlineStatus::Offline => ProtoStatus::Offline,
    }
}

/// Convert session_manager SessionInfo → proto SessionInfo.
pub fn to_proto_info(info: &SessionInfo) -> ProtoInfo {
    ProtoInfo {
        user_id: info.user_id.to_string(),
        session_count: info.session_count as u32,
        workspaces: info.workspaces.iter().map(|w| w.to_string()).collect(),
        latest_session: info.latest_session.as_ref().map(to_proto_session),
    }
}

/// Convert prost_types::Timestamp → chrono::DateTime<Utc>.
pub fn prost_ts_to_chrono(ts: &prost_types::Timestamp) -> DateTime<Utc> {
    DateTime::from_timestamp(ts.seconds, ts.nanos as u32)
        .unwrap_or_else(Utc::now)
}

/// Convert proto OnlineStatus → session_manager OnlineStatus.
pub fn from_proto_status(s: ProtoStatus) -> OnlineStatus {
    match s {
        ProtoStatus::Online => OnlineStatus::Online,
        ProtoStatus::Idle => OnlineStatus::Idle,
        ProtoStatus::Offline => OnlineStatus::Offline,
        ProtoStatus::Unspecified => OnlineStatus::Offline,
    }
}

/// Parse a string UUID. Returns None on parse failure.
pub fn parse_uuid(s: &str) -> Option<uuid::Uuid> {
    uuid::Uuid::parse_str(s).ok()
}
