use anyhow::{bail, Result};
use clap::Parser;
use derive_more::FromStr;
use futures_lite::StreamExt;
use super::{AuthorsClient, ConsoleEnv};
use crate::{cli::fmt_short, Author, AuthorId};
#[allow(missing_docs)]
#[derive(Debug, Clone, Parser)]
pub enum AuthorCommands {
    Switch { author: AuthorId },
    Create {
        #[clap(long)]
        switch: bool,
    },
    Delete { author: AuthorId },
    Export { author: AuthorId },
    Import { author: String },
    Default {
        #[clap(long)]
        switch: bool,
    },
    #[clap(alias = "ls")]
    List,
}
impl AuthorCommands {
    pub async fn run(self, authors: &AuthorsClient, env: &ConsoleEnv) -> Result<()> {
        match self {
            Self::Switch { author } => {
                env.set_author(author)?;
                println!("Active author is now {}", fmt_short(author.as_bytes()));
            }
            Self::List => {
                let mut stream = authors.list().await?;
                while let Some(author_id) = stream.try_next().await? {
                    println!("{}", author_id);
                }
            }
            Self::Default { switch } => {
                if switch && !env.is_console() {
                    bail!("The --switch flag is only supported within the Iroh console.");
                }
                let author_id = authors.default().await?;
                println!("{}", author_id);
                if switch {
                    env.set_author(author_id)?;
                    println!("Active author is now {}", fmt_short(author_id.as_bytes()));
                }
            }
            Self::Create { switch } => {
                if switch && !env.is_console() {
                    bail!("The --switch flag is only supported within the Iroh console.");
                }
                let author_id = authors.create().await?;
                println!("{}", author_id);
                if switch {
                    env.set_author(author_id)?;
                    println!("Active author is now {}", fmt_short(author_id.as_bytes()));
                }
            }
            Self::Delete { author } => {
                authors.delete(author).await?;
                println!("Deleted author {}", fmt_short(author.as_bytes()));
            }
            Self::Export { author } => match authors.export(author).await? {
                Some(author) => {
                    println!("{}", author);
                }
                None => {
                    println!("No author found {}", fmt_short(author.as_bytes()));
                }
            },
            Self::Import { author } => match Author::from_str(&author) {
                Ok(author) => {
                    let id = author.id();
                    authors.import(author).await?;
                    println!("Imported {}", fmt_short(id.as_bytes()));
                }
                Err(err) => {
                    eprintln!("Invalid author key: {}", err);
                }
            },
        }
        Ok(())
    }
}