use clap::Parser;

/// TCP relay server mode
#[derive(Parser, Debug, Clone)]
#[clap(
    author,
    version,
    about,
    long_about = "TCP-over-HTTP server. This program can be configured behind a reverse-proxy (without TLS authentication)."
)]
pub struct ServerConfig {
    /// Access tokens
    #[clap(short, long)]
    pub tokens: Vec<String>,

    /// Access tokens stored in a file, one token per line
    #[clap(long)]
    pub tokens_file: Option<String>,

    /// Forwarded ports
    #[clap(short, long)]
    pub ports: Vec<u16>,

    /// Upstream server
    #[clap(short, long, default_value = "127.0.0.1")]
    pub upstream_server: String,

    /// HTTP server listen address
    #[clap(short, long, default_value = "0.0.0.0:8000")]
    pub listen_address: String,

    /// Increment ports on client. Useful for debugging and running both client and server
    /// on the same machine
    #[clap(short, long, default_value_t = 0)]
    pub increment_ports: u16,

    /// TLS certificate. Specify also private key to use HTTPS/TLS instead of HTTP
    #[clap(long)]
    pub tls_cert: Option<String>,

    /// TLS private key. Specify also certificate to use HTTPS/TLS instead of HTTP
    #[clap(long)]
    pub tls_key: Option<String>,

    /// Restrict TLS client authentication to certificates signed directly or indirectly by the
    /// provided root certificates
    ///
    /// This option automatically enable TLS client authentication
    #[clap(long)]
    pub tls_client_auth_root_cert: Option<String>,

    /// TLS client authentication revocation list (CRL file)
    #[clap(long)]
    pub tls_revocation_list: Option<String>,
}

impl ServerConfig {
    pub fn has_token_auth(&self) -> bool {
        !self.tokens.is_empty()
    }

    pub fn has_tls_config(&self) -> bool {
        self.tls_cert.is_some() && self.tls_key.is_some()
    }

    pub fn has_tls_client_auth(&self) -> bool {
        self.tls_client_auth_root_cert.is_some()
    }

    pub fn has_auth(&self) -> bool {
        self.has_token_auth() || self.has_tls_client_auth()
    }
}

#[cfg(test)]
mod test {
    use crate::tcp_relay_server::server_config::ServerConfig;

    #[test]
    fn verify_cli() {
        use clap::CommandFactory;
        ServerConfig::command().debug_assert()
    }
}