//! Configuration options for the server.
use std::{
    borrow::Cow,
    path::{Path, PathBuf},
};

use clap::{Args, ValueEnum};

/// Server configuration options.
#[derive(Debug, Clone, Args)]
pub struct ServerOptions {
    /// Port to listen on.
    #[arg(
        short = 'P',
        long = "port",
        default_value = "8080",
        env = "OPSERVE_PORT"
    )]
    pub port: u16,
    /// Host address to bind to.
    #[arg(
        short = 'B',
        long = "bind-host",
        default_value = "localhost",
        env = "OPSERVE_BIND_HOST"
    )]
    pub bind_host: String,
    /// Server hostname (default uses Host: header).
    #[arg(short = 'H', long = "host", env = "OPSERVE_HOST")]
    pub host: Option<String>,
    /// Location of the site content root.
    #[arg(short = 'R', long = "root", default_value = ".", env = "OPSERVE_ROOT")]
    pub content_root: PathBuf,
    /// Specify alternate path to manifest file.
    #[arg(short = 'M', long = "manifest")]
    pub alt_manifest: Option<PathBuf>,
    /// Expose request information page.
    #[arg(long = "server-info", env = "OPSERVE_SERVER_INFO")]
    pub expose_info: bool,
    /// Blindly trust proxy headers (otherwise only trust localhost).
    #[arg(long = "trust-proxy", env = "OPSERVE_TRUST_PROXY")]
    pub trust_proxy: bool,

    /// Interpret headers from the specified CDN (useful for origin servers).
    #[arg(long = "cdn", env = "OPSERVE_CDN")]
    pub cdn: Option<CDN>,
    /// Shared secret to expect in an X-OPServe-Auth header to establish CDN trust.
    #[arg(long = "cdn-secret", env = "OPSERVE_CDN_SECRET")]
    pub cdn_secret: Option<String>,
}

/// Known CDN implementations.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Debug, Ord, ValueEnum)]
pub enum CDN {
    /// Bunny CDN.
    Bunny,
}

impl ServerOptions {
    pub fn manifest_path(&self) -> Cow<'_, Path> {
        if let Some(path) = &self.alt_manifest {
            path.into()
        } else {
            let root = &self.content_root;
            let path = root.join(".opserve/manifest.json");
            path.into()
        }
    }
}
