Documentation
use std::sync::Arc;

use rustls_pemfile::{certs, private_key};
use rustls_pki_types::{CertificateDer, PrivateKeyDer};
use s2n_quic::provider::tls::s2n_tls::config::Config;

use crate::{Error, Result};

#[derive(Debug)]
pub struct Rusttls {
  pub fullchain: Vec<CertificateDer<'static>>,
  pub key: PrivateKeyDer<'static>,
}

#[derive(Debug, Clone)]
pub struct Cert {
  pub s2n: Arc<Config>,
  pub rustls: Arc<Rusttls>,
}

impl Cert {
  pub fn new(fullchain: impl Into<String>, key: impl Into<String>) -> Result<Self> {
    let fullchain = fullchain.into();
    let key = key.into();
    let mut cert_reader = std::io::Cursor::new(fullchain.as_bytes());

    let mut key_reader = std::io::Cursor::new(key.as_bytes());

    let tls_config = s2n_quic::provider::tls::s2n_tls::Server::builder()
      .with_application_protocols(&[b"h3".to_vec()])?
      .with_certificate(fullchain.clone(), key.clone())?
      .build()?;

    let rustls = Arc::new(Rusttls {
      fullchain: certs(&mut cert_reader)
        .collect::<std::result::Result<Vec<_>, _>>()
        .map_err(|e| Error::CertParse(format!("证书解析失败: {e:?}")))?,
      key: private_key(&mut key_reader)
        .map_err(|e| Error::CertParse(format!("私钥解析失败: {e:?}")))?
        .ok_or(Error::PrivateKeyNotFound)?,
    });

    Ok(Cert {
      rustls,
      s2n: Arc::new(tls_config.into()),
    })
  }
}