mod client;
mod daemon;
mod db;
mod printers;

use anyhow::Result;
use clap::{Parser, Subcommand};
use log::LevelFilter;

/// A command line interface for the Kordophone library and daemon
#[derive(Parser)]
#[command(name = "kpcli")]
struct Cli {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand)]
enum Commands {
    /// Commands for api client operations
    Client {
        #[command(subcommand)]
        command: client::Commands,
    },

    /// Commands for the cache database
    Db {
        #[command(subcommand)]
        command: db::Commands,
    },

    /// Commands for interacting with the daemon
    Daemon {
        #[command(subcommand)]
        command: daemon::Commands,
    },
}

async fn run_command(command: Commands) -> Result<()> {
    match command {
        Commands::Client { command } => client::Commands::run(command).await,
        Commands::Db { command } => db::Commands::run(command).await,
        Commands::Daemon { command } => daemon::Commands::run(command).await,
    }
}

fn initialize_logging() {
    // Weird: is this the best way to do this?
    let log_level = std::env::var("RUST_LOG")
        .map(|s| s.parse::<LevelFilter>().unwrap_or(LevelFilter::Info))
        .unwrap_or(LevelFilter::Info);

    env_logger::Builder::from_default_env()
        .format_timestamp_secs()
        .filter_level(log_level)
        .init();
}

#[tokio::main]
async fn main() {
    initialize_logging();

    let cli = Cli::parse();

    run_command(cli.command)
        .await
        .map_err(|e| println!("Error: {}", e))
        .err();
}
