use axum::extract::FromRef;
use config::{Config, ConfigError, Environment};
use dotenvy::dotenv;
use serde::Deserialize;

use crate::app_state::AppState;

#[derive(Clone, Debug, Deserialize)]
pub struct Settings {
    #[serde(default)]
    pub base_path: String,

    pub database_url: String,

    #[serde(default = "default_host")]
    pub host: String,

    #[serde(default = "default_port")]
    pub port: u16,

    pub auth: Auth,
}

fn default_port() -> u16 {
    3000
}

fn default_host() -> String {
    "127.0.0.1".to_string()
}

#[derive(Clone, Debug, Deserialize)]
pub struct Auth {
    pub client_id: String,
    pub client_secret: String,
    pub redirect_url: String,
    pub auth_url: String,
    pub token_url: String,
    pub userinfo_url: String,

    #[serde(default = "default_cookie_name")]
    pub cookie_name: String,
}

fn default_cookie_name() -> String {
    "CALLOUT_SESSION".to_string()
}

impl Settings {
    pub fn load() -> Result<Self, ConfigError> {
        if let Err(_) = dotenv() {
            println!("Couldn't load .env file.");
        }
        let s = Config::builder()
            .add_source(Environment::default())
            .build()?;
        s.try_deserialize()
    }
}

impl FromRef<AppState> for Settings {
    fn from_ref(state: &AppState) -> Self {
        state.settings.clone()
    }
}
