use std::path::PathBuf;

use anyhow::Result;
use clap::Parser;
use pubky_homeserver::{tracing::init_tracing_logs_if_set, HomeserverApp};

fn default_config_dir_path() -> PathBuf {
    dirs::home_dir().unwrap_or_default().join(".pubky")
}

/// Validate that the data_dir path is a directory.
/// It doesnt need to exist, but if it does, it needs to be a directory.
fn validate_config_dir_path(path: &str) -> Result<PathBuf, String> {
    let path = PathBuf::from(path);
    if path.exists() && path.is_file() {
        return Err(format!("Given path is not a directory: {}", path.display()));
    }
    Ok(path)
}

#[derive(Parser, Debug)]
#[command(version = env!("CARGO_PKG_VERSION"))]
struct Cli {
    /// Path to config file. Defaults to ~/.pubky/config.toml
    #[clap(short, long, default_value_os_t = default_config_dir_path(), value_parser = validate_config_dir_path)]
    data_dir: PathBuf,
}

#[tokio::main]
async fn main() -> Result<()> {
    let args = Cli::parse();
    init_tracing_logs_if_set(&args.data_dir)?;

    tracing::info!("Use data directory: {}", args.data_dir.display());
    let server = HomeserverApp::start_with_persistent_data_dir_path(args.data_dir).await?;

    tracing::info!(
        "Homeserver HTTP listening on {}",
        server.client_server().icann_http_url_string()
    );

    tracing::info!(
        "Homeserver Pubky TLS listening on {}",
        server.client_server().pubky_tls_dns_url_string(),
    );
    tracing::info!(
        "Homeserver Pubky TLS listening on {}",
        server.client_server().pubky_tls_ip_url_ring()
    );
    if let Some(admin_server) = server.admin_server() {
        tracing::info!(
            "Admin server listening on http://{}",
            admin_server.listen_socket()
        );
    }
    if let Some(metrics_server) = server.metrics_server() {
        tracing::info!(
            "Metrics server listening on http://{}",
            metrics_server.listen_socket()
        );
    }

    tracing::info!("Press Ctrl+C to stop the Homeserver");
    tokio::signal::ctrl_c().await?;

    tracing::info!("Shutting down Homeserver");

    Ok(())
}
