use std::env;

use anyhow::Context;

const DATABASE_URL_KEY: &str = "DATABASE_URL";
const SMTP_HOST: &str = "SMTP_HOST";
const SMTP_PORT: &str = "SMTP_PORT";
const SMTP_USERNAME: &str = "SMTP_USERNAME";
const SMTP_PASSWORD: &str = "SMTP_PASSWORD";
const SMTP_SENDER: &str = "SMTP_SENDER";
const JWT_SECRET: &str = "JWT_SECRET";
const HASH_ID: &str = "HASH_ID";

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Config {
    pub database_url: String,

    pub smtp_host: String,
    pub smtp_port: u16,
    pub smtp_username: String,
    pub smtp_password: String,
    pub smtp_sender: String,

    pub jwt_secret: String,
    pub hash_id: String,
}

impl Config {
    pub fn from_env() -> anyhow::Result<Config> {
        let database_url = load_env(DATABASE_URL_KEY)?;
        let smtp_host = load_env(SMTP_HOST)?;
        let smtp_port = load_env(SMTP_PORT)?.parse()?;
        let smtp_username = load_env(SMTP_USERNAME)?;
        let smtp_password = load_env(SMTP_PASSWORD)?;
        let smtp_sender = load_env(SMTP_SENDER)?;
        let jwt_secret = load_env(JWT_SECRET)?;
        let hash_id = load_env(HASH_ID)?;

        Ok(Config {
            database_url,
            smtp_host,
            smtp_port,
            smtp_username,
            smtp_password,
            smtp_sender,
            jwt_secret,
            hash_id,
        })
    }
}

fn load_env(key: &str) -> anyhow::Result<String> {
    env::var(key).with_context(|| format!("failed to load environment variable {}", key))
}
