use std::{fs::create_dir, io::ErrorKind, path::PathBuf};

use tz::{TimeZone, UtcDateTime};

/// Returns the directory in which screenshots are to be saved.
/// Follows a best-effort fallback pattern.
pub(crate) fn screenshots_directory() -> anyhow::Result<PathBuf> {
    let path = if let Some(s) = std::env::var_os("XDG_SCREENSHOTS_DIR") {
        s.into()
    } else if let Some(s) = std::env::var_os("XDG_PICTURES_DIR") {
        PathBuf::from(s).join("screenshots")
    } else if let Some(home) = std::env::var_os("HOME") {
        let home = PathBuf::from(home);
        let pictures_fallback = home.join("Pictures");
        if pictures_fallback.exists() {
            pictures_fallback
        } else {
            home.join("screenshots")
        }
    } else if let Ok(cwd) = std::env::current_dir() {
        cwd
    } else {
        anyhow::bail!("$HOME isn't defined; no fallback for screenshot location");
    };

    match create_dir(&path) {
        Ok(()) => Ok(path),
        Err(err) if err.kind() == ErrorKind::AlreadyExists => Ok(path),
        Err(err) => Err(err.into()),
    }
}

fn screenshot_filename() -> anyhow::Result<String> {
    let local = TimeZone::local()?;
    let utc_now = UtcDateTime::now()?;
    let now = utc_now.project(local.as_ref())?;

    let formatted_string = format!(
        "Screenshot.from.{:04}-{:02}-{:02}.at.{:02}_{:02}_{:02}.{:09}.png",
        now.year(),
        now.month(),
        now.month_day(),
        now.hour(),
        now.minute(),
        now.second(),
        now.nanoseconds()
    );

    Ok(formatted_string)
}

pub(crate) fn screenshot_filepath() -> anyhow::Result<PathBuf> {
    let filename = screenshot_filename()?;
    Ok(screenshots_directory()?.join(filename))
}
