use anyhow::Context;

#[derive(Clone, Debug)]
pub struct Config {
    pub database_url: String,
    pub bind_addr: String,
    /// External base URL of the app, e.g. https://photos.example.com (no trailing slash).
    pub public_url: String,
    pub session_secret: String,
    pub s3_bucket: String,
    pub s3_endpoint: Option<String>,
    pub s3_region: String,
    pub s3_access_key: String,
    pub s3_secret_key: String,
    pub s3_force_path_style: bool,
    pub oidc_issuer: String,
    pub oidc_client_id: String,
    pub oidc_client_secret: String,
    /// Lowercased email addresses allowed to sign in as photographer.
    pub allowed_emails: Vec<String>,
    pub static_dir: String,
    pub worker_concurrency: usize,
    /// DEV ONLY: if set, /api/auth/login skips OIDC entirely and signs in as
    /// this email. Never set in production.
    pub dev_autologin_email: Option<String>,
}

fn required(name: &str) -> anyhow::Result<String> {
    std::env::var(name).with_context(|| format!("missing required env var {name}"))
}

fn optional(name: &str) -> Option<String> {
    std::env::var(name).ok().filter(|v| !v.is_empty())
}

impl Config {
    pub fn from_env() -> anyhow::Result<Self> {
        let session_secret = required("SESSION_SECRET")?;
        anyhow::ensure!(
            session_secret.len() >= 32,
            "SESSION_SECRET must be at least 32 characters"
        );
        let public_url = required("PUBLIC_URL")?.trim_end_matches('/').to_string();
        let dev_autologin_email = optional("DEV_AUTOLOGIN_EMAIL");
        anyhow::ensure!(
            dev_autologin_email.is_none() || !public_url.starts_with("https://"),
            "DEV_AUTOLOGIN_EMAIL must not be set when PUBLIC_URL is https:// — it disables login"
        );
        Ok(Self {
            database_url: required("DATABASE_URL")?,
            bind_addr: optional("BIND_ADDR").unwrap_or_else(|| "0.0.0.0:8080".into()),
            public_url,
            session_secret,
            s3_bucket: required("S3_BUCKET")?,
            s3_endpoint: optional("S3_ENDPOINT"),
            s3_region: optional("S3_REGION").unwrap_or_else(|| "us-east-1".into()),
            s3_access_key: required("S3_ACCESS_KEY")?,
            s3_secret_key: required("S3_SECRET_KEY")?,
            s3_force_path_style: optional("S3_FORCE_PATH_STYLE")
                .map(|v| v == "1" || v.eq_ignore_ascii_case("true"))
                .unwrap_or(false),
            oidc_issuer: required("OIDC_ISSUER")?.trim_end_matches('/').to_string(),
            oidc_client_id: required("OIDC_CLIENT_ID")?,
            oidc_client_secret: required("OIDC_CLIENT_SECRET")?,
            allowed_emails: required("ALLOWED_EMAILS")?
                .split(',')
                .map(|s| s.trim().to_lowercase())
                .filter(|s| !s.is_empty())
                .collect(),
            static_dir: optional("STATIC_DIR").unwrap_or_else(|| "frontend/dist".into()),
            worker_concurrency: optional("WORKER_CONCURRENCY")
                .and_then(|v| v.parse().ok())
                .unwrap_or(2),
            dev_autologin_email,
        })
    }

    pub fn cookie_secure(&self) -> bool {
        self.public_url.starts_with("https://")
    }
}
