use std::path::PathBuf;
use std::process::Command;

/// Candidate relative paths to the client log under a game install directory.
const LOG_RELATIVE: &[&str] = &["logs/Client.txt", "logs/client.txt"];

/// Common install roots (relative to $HOME) where Path of Exile 2 may live.
const GAME_ROOTS: &[&str] = &[
    ".local/share/Steam/steamapps/common/Path of Exile 2",
    ".steam/steam/steamapps/common/Path of Exile 2",
    ".steam/root/steamapps/common/Path of Exile 2",
    ".var/app/com.valvesoftware.Steam/.local/share/Steam/steamapps/common/Path of Exile 2",
    "Games/Path of Exile 2",
    // PoE1 fallbacks
    ".local/share/Steam/steamapps/common/Path of Exile",
    ".steam/steam/steamapps/common/Path of Exile",
];

/// Try to locate existing Client.txt files in well-known locations.
pub fn detect_log_paths() -> Vec<String> {
    let mut found = Vec::new();
    let home = match dirs::home_dir() {
        Some(h) => h,
        None => return found,
    };

    // 1) Hard-coded common roots.
    for root in GAME_ROOTS {
        for rel in LOG_RELATIVE {
            let mut p = home.join(root);
            p.push(rel);
            if p.is_file() {
                found.push(p.to_string_lossy().to_string());
            }
        }
    }

    // 2) Parse Steam's libraryfolders.vdf for additional library locations.
    for vdf in steam_library_paths(&home) {
        for sub in ["Path of Exile 2", "Path of Exile"] {
            for rel in LOG_RELATIVE {
                let mut p = vdf.join("steamapps/common").join(sub);
                p.push(rel);
                if p.is_file() {
                    let s = p.to_string_lossy().to_string();
                    if !found.contains(&s) {
                        found.push(s);
                    }
                }
            }
        }
    }

    found
}

fn steam_library_paths(home: &PathBuf) -> Vec<PathBuf> {
    let mut libs = Vec::new();
    let candidates = [
        ".local/share/Steam/steamapps/libraryfolders.vdf",
        ".steam/steam/steamapps/libraryfolders.vdf",
    ];
    for c in candidates {
        let p = home.join(c);
        if let Ok(text) = std::fs::read_to_string(&p) {
            // crude VDF scan: capture every "path"  "…" value
            for line in text.lines() {
                let line = line.trim();
                if line.starts_with("\"path\"") {
                    if let Some(start) = line[6..].find('"') {
                        let rest = &line[6 + start + 1..];
                        if let Some(end) = rest.find('"') {
                            libs.push(PathBuf::from(&rest[..end]));
                        }
                    }
                }
            }
        }
    }
    libs
}

/// Current global mouse pointer position (X11/XWayland), used for AFK detection.
/// XScreenSaver idle isn't available under XWayland, so we poll the pointer.
pub fn mouse_position() -> Option<(i32, i32)> {
    let out = Command::new("xdotool")
        .arg("getmouselocation")
        .output()
        .ok()?;
    if !out.status.success() {
        return None;
    }
    let s = String::from_utf8_lossy(&out.stdout);
    // format: "x:3814 y:8 screen:0 window:..."
    let mut x = None;
    let mut y = None;
    for tok in s.split_whitespace() {
        if let Some(v) = tok.strip_prefix("x:") {
            x = v.parse().ok();
        } else if let Some(v) = tok.strip_prefix("y:") {
            y = v.parse().ok();
        }
    }
    Some((x?, y?))
}

/// Returns the title of the currently focused X11 window, if obtainable.
pub fn active_window_title() -> Option<String> {
    let out = Command::new("xdotool")
        .args(["getactivewindow", "getwindowname"])
        .output()
        .ok()?;
    if out.status.success() {
        let s = String::from_utf8_lossy(&out.stdout).trim().to_string();
        if s.is_empty() {
            None
        } else {
            Some(s)
        }
    } else {
        None
    }
}
