use std::fmt;

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct SessionId(u64);

impl SessionId {
    pub fn new(id: u64) -> Self {
        Self(id)
    }

    pub fn as_u64(&self) -> u64 {
        self.0
    }
}

impl fmt::Display for SessionId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

#[derive(Clone, Debug)]
pub(crate) struct PtyOptions {
    pub term: String,
    pub cols: u32,
    pub rows: u32,
    pub pix_width: u32,
    pub pix_height: u32,
}

impl Default for PtyOptions {
    fn default() -> Self {
        Self {
            term: "xterm-256color".to_string(),
            cols: 80,
            rows: 24,
            pix_width: 0,
            pix_height: 0,
        }
    }
}

#[derive(Clone, Debug)]
pub enum SessionEvent {
    Stdout(Vec<u8>),
    Stderr(Vec<u8>),
    Error(String),
    Closed { exit_status: Option<u32> },
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn session_id_new_and_as_u64() {
        let id = SessionId::new(42);
        assert_eq!(id.as_u64(), 42);
    }

    #[test]
    fn session_id_display() {
        let id = SessionId::new(123);
        assert_eq!(format!("{}", id), "123");
    }

    #[test]
    fn session_id_equality() {
        let a = SessionId::new(1);
        let b = SessionId::new(1);
        let c = SessionId::new(2);
        assert_eq!(a, b);
        assert_ne!(a, c);
    }

    #[test]
    fn session_id_copy() {
        let a = SessionId::new(99);
        let b = a;
        assert_eq!(a, b, "SessionId should implement Copy");
    }

    #[test]
    fn session_id_hash() {
        use std::collections::HashMap;
        let mut map = HashMap::new();
        map.insert(SessionId::new(1), "first");
        map.insert(SessionId::new(1), "second");
        assert_eq!(map.len(), 1, "same SessionId should overwrite");
    }

    #[test]
    fn pty_options_default() {
        let opts = PtyOptions::default();
        assert_eq!(opts.term, "xterm-256color");
        assert_eq!(opts.cols, 80);
        assert_eq!(opts.rows, 24);
        assert_eq!(opts.pix_width, 0);
        assert_eq!(opts.pix_height, 0);
    }
}
