//! Data directory resolution.
//!
//! The binary locates its `data/` directory using the following search order:
//!
//! 1. `REALM_DATA` environment variable (explicit override).
//! 2. `data/` next to the binary (portable installs, .app bundles, Windows).
//! 3. `data/` in the current working directory (development).
//! 4. Platform user data directory:
//!    - Linux: `$XDG_DATA_HOME/realm/data` or `~/.local/share/realm/data`
//!    - macOS: `~/Library/Application Support/realm/data`
//!    - Windows: `%APPDATA%\realm\data`
//!
//! The first path that exists wins. Panics if none are found.

use std::env;
use std::path::PathBuf;
use std::sync::OnceLock;

static DATA_DIR: OnceLock<PathBuf> = OnceLock::new();

/// Platform-specific user data directory for realm.
fn platform_data_dir() -> Option<PathBuf> {
    #[cfg(target_os = "linux")]
    {
        let base = env::var("XDG_DATA_HOME")
            .map(PathBuf::from)
            .unwrap_or_else(|_| {
                let home = env::var("HOME").expect("HOME not set");
                PathBuf::from(home).join(".local/share")
            });
        Some(base.join("realm/data"))
    }

    #[cfg(target_os = "macos")]
    {
        let home = env::var("HOME").ok()?;
        Some(PathBuf::from(home).join("Library/Application Support/realm/data"))
    }

    #[cfg(target_os = "windows")]
    {
        env::var("APPDATA")
            .ok()
            .map(|d| PathBuf::from(d).join("realm\\data"))
    }

    #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
    {
        None
    }
}

/// Resolve and cache the data directory. Panics if not found.
pub fn data_dir() -> &'static PathBuf {
    DATA_DIR.get_or_init(|| {
        let candidates: Vec<PathBuf> = vec![
            // 1. Explicit override
            env::var("REALM_DATA").ok().map(PathBuf::from),
            // 2. Next to the binary
            env::current_exe()
                .ok()
                .and_then(|p| p.parent().map(|d| d.join("data"))),
            // 3. Working directory
            Some(PathBuf::from("data")),
            // 4. Platform user data directory
            platform_data_dir(),
        ]
        .into_iter()
        .flatten()
        .collect();

        for path in &candidates {
            if path.is_dir() {
                return path.clone();
            }
        }

        panic!(
            "Could not find data directory. Searched:\n{}",
            candidates
                .iter()
                .map(|p| format!("  - {}", p.display()))
                .collect::<Vec<_>>()
                .join("\n")
        );
    })
}

/// Resolve a path within the data directory.
pub fn data_path(relative: &str) -> PathBuf {
    data_dir().join(relative)
}
