use anyhow::*;
use gas::prelude::*;

pub mod cache;
pub mod errors;
pub mod metrics;
pub mod routing;
pub mod shared_state;
pub mod tls;

#[tracing::instrument(skip_all)]
pub async fn start(config: rivet_config::Config, pools: rivet_pools::Pools) -> Result<()> {
	let cache = rivet_cache::CacheInner::from_env(&config, pools.clone())?;
	let ctx = StandaloneCtx::new(
		db::DatabaseKv::new(config.clone(), pools.clone()).await?,
		config.clone(),
		pools,
		cache,
		"guard",
		Id::new_v1(config.dc_label()),
		Id::new_v1(config.dc_label()),
	)?;

	// Initialize rustls with the default ring CryptoProvider.
	let provider = rustls::crypto::ring::default_provider();
	if provider.install_default().is_err() {
		tracing::debug!("crypto provider already installed in this process");
	}

	// Share shared context
	let shared_state = shared_state::SharedState::new(&config, ctx.ups()?);
	shared_state.start().await?;

	// Create handlers
	let routing_fn = routing::create_routing_function(&ctx, shared_state.clone());
	let cache_key_fn = cache::create_cache_key_function();
	let cert_resolver = tls::create_cert_resolver(&ctx).await?;

	if let Some(_) = &cert_resolver {
		tracing::info!("TLS certificate resolver configured");
	} else {
		tracing::info!("No TLS configuration found, HTTPS will not be enabled");
	}

	// Start the server
	tracing::info!("starting proxy server");
	rivet_guard_core::run_server(config, routing_fn, cache_key_fn, cert_resolver).await
}
