use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};

pub struct CliChannel {
    read: BufReader<tokio::io::Stdin>,
    write: tokio::io::Stdout,
}

impl CliChannel {
    pub fn new() -> Self {
        Self {
            read: BufReader::new(tokio::io::stdin()),
            write: tokio::io::stdout(),
        }
    }

    pub async fn read_line(&mut self, prompt: &str) -> Result<Option<String>, std::io::Error> {
        print!("{}", prompt);
        self.write.flush().await?;

        let mut line = String::new();
        let bytes_read = self.read.read_line(&mut line).await?;

        if bytes_read == 0 {
            return Ok(None);
        }

        Ok(Some(line.trim_end().to_string()))
    }

    pub async fn write_line(&mut self, content: &str) -> Result<(), std::io::Error> {
        self.write.write_all(content.as_bytes()).await?;
        self.write.write_all(b"\n").await?;
        self.write.flush().await
    }

    pub async fn write_response(&mut self, content: &str) -> Result<(), std::io::Error> {
        for line in content.lines() {
            self.write.write_all(b"  ").await?;
            self.write.write_all(line.as_bytes()).await?;
            self.write.write_all(b"\n").await?;
        }
        self.write.flush().await
    }
}

impl Default for CliChannel {
    fn default() -> Self {
        Self::new()
    }
}
