//! Persistent CLI config (`~/.sprouts/config.json`) — stores the API/web URLs
//! and the saved session (tokens + user).

use std::fs;
use std::path::PathBuf;

use serde::{Deserialize, Serialize};

#[derive(Debug, Default, Serialize, Deserialize)]
pub struct Config {
    pub api_url: Option<String>,
    pub web_url: Option<String>,
    pub token: Option<String>,
    pub refresh_token: Option<String>,
    pub user_id: Option<String>,
    pub email: Option<String>,
}

impl Config {
    /// API base URL: `SPROUTS_API_URL` env → saved config → default.
    pub fn api_url(&self) -> String {
        std::env::var("SPROUTS_API_URL")
            .ok()
            .or_else(|| self.api_url.clone())
            .unwrap_or_else(|| "https://api.sprouts.run".into())
    }

    /// Web base URL: `SPROUTS_WEB_URL` env → saved config → default.
    pub fn web_url(&self) -> String {
        std::env::var("SPROUTS_WEB_URL")
            .ok()
            .or_else(|| self.web_url.clone())
            .unwrap_or_else(|| "https://sprouts.run".into())
    }

    pub fn clear_auth(&mut self) {
        self.token = None;
        self.refresh_token = None;
        self.user_id = None;
        self.email = None;
    }
}

/// Path to the config file (`~/.sprouts/config.json`).
pub fn path() -> anyhow::Result<PathBuf> {
    let home = dirs::home_dir().ok_or_else(|| anyhow::anyhow!("could not find home directory"))?;
    Ok(home.join(".sprouts").join("config.json"))
}

pub fn load() -> anyhow::Result<Config> {
    let path = path()?;
    if !path.exists() {
        return Ok(Config::default());
    }
    Ok(serde_json::from_str(&fs::read_to_string(path)?)?)
}

pub fn save(config: &Config) -> anyhow::Result<()> {
    let path = path()?;
    if let Some(dir) = path.parent() {
        fs::create_dir_all(dir)?;
    }
    fs::write(&path, serde_json::to_string_pretty(config)?)?;
    // The file holds tokens — make it user-only.
    #[cfg(unix)]
    {
        use std::os::unix::fs::PermissionsExt;
        let _ = fs::set_permissions(&path, fs::Permissions::from_mode(0o600));
    }
    Ok(())
}
