Documentation
use std::{net::SocketAddr, path::PathBuf, sync::Arc};

use axum::{Router, response::Html, routing::get};
use faststr::FastStr;
use i18n_gateway::{
  cert_loader::CertLoader,
  route::{Protocol, Route, Upstream, UpstreamSiteSet},
  srv,
};
use rustls;

const MANIFEST_DIR: &str = env!("CARGO_MANIFEST_DIR");

async fn start_upstream_server(addr: SocketAddr) {
  let app = Router::new().route(
    "/",
    get(move || async move { Html(format!("Hello, World! from {}", addr)) }),
  );
  let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
  axum::serve(listener, app).await.unwrap();
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
  rustls::crypto::aws_lc_rs::default_provider()
    .install_default()
    .expect("failed to install aws-lc-rs as default provider");
  env_logger::init();

  // 启动两个上游服务器用于测试
  let upstream_addr1: SocketAddr = "127.0.0.1:8081".parse()?;
  let upstream_addr2: SocketAddr = "127.0.0.1:8082".parse()?;
  tokio::spawn(start_upstream_server(upstream_addr1));
  tokio::spawn(start_upstream_server(upstream_addr2));

  // HTTP/1.1 代理地址
  let h1_addr: SocketAddr = "0.0.0.0:8080".parse()?;
  let h2_addr: SocketAddr = "0.0.0.0:8443".parse()?;
  let h3_addr: SocketAddr = "0.0.0.0:8443".parse()?;

  let mut route = Route::default();
  let upstream = Arc::new(Upstream {
    addr_li: vec![upstream_addr1, upstream_addr2].into_boxed_slice(),
    connect_timeout_sec: 3,
    request_timeout_sec: 10,
    max_retry: 3,
    protocol: Protocol::H1,
  });

  let upstream_name = FastStr::from("test_upstream");
  route.upstream_site.insert(
    upstream_name.clone(),
    UpstreamSiteSet {
      upstream: upstream.clone(),
      host_set: Default::default(),
    },
  );

  route.set("test.018007.xyz", "018007.xyz", upstream_name.clone());
  route.set("018007.xyz", "018007.xyz", upstream_name);

  let cert_db = i18n_gateway::cert_loader::CertDir {
    base: PathBuf::from(MANIFEST_DIR).join("examples/ssl"),
  };
  let cert_loader = CertLoader::new(cert_db);

  // 启动代理服务器
  srv(Arc::new(route), cert_loader, h1_addr, h2_addr, h3_addr).await?;

  Ok(())
}