pub mod cmd;
pub mod handler;
pub mod middleware;
pub mod router;
pub mod service;

use std::{panic, sync::Arc, time::Duration};

use clap::Parser;
use figlet_rs::FIGlet;
use infra::core::{AppState, config, logger};
use neon_rs::sql::set_sql_logger;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let std_font = FIGlet::standard().unwrap();
    println!("{}", std_font.convert("{{ app_name }}").unwrap());

    let cli = cmd::Cli::parse();

    // init config
    config::init(&cli.config)?;

    // _guard 必须在 main 函数中才能使日志生效
    let _guard = logger::init();

    // catch panic
    panic::set_hook(Box::new(|e| {
        tracing::error!(panic = %e);
    }));

    set_sql_logger(|sql, cost, err| match err {
        Some(e) => {
            tracing::error!(sql = sql, cost_ms = cost.as_millis(), err = %e, "sql error");
        }
        None => {
            if cost > Duration::from_millis(200) {
                tracing::warn!(sql = sql, cost_ms = cost.as_millis(), "slow sql");
            } else {
                tracing::info!(sql = sql, cost_ms = cost.as_millis(), "sql");
            }
        }
    });

    let state = Arc::new(AppState::default());
    // let state = Arc::new(AppState::new().await?);

    match cli.command {
        Some(cmd::Command::Hello { name }) => cmd::hello::run(name),
        Some(cmd::Command::Serve) => cmd::serve::run(state.clone()).await,
        _ => {
            println!("🦀 Welcome to use noble-gase[Actix-Web] scaffold");
        }
    }

    Ok(())
}
