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

use anyhow::Context;
use time::{format_description::FormatItem, OffsetDateTime};

const FILENAME_FMT: &[FormatItem] = time::macros::format_description!(
    "Screenshot.from.[year]-[month]-[day].at.[hour]_[minute]_[second].[subsecond digits:9].png"
);

/// 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()),
    }
}

pub(crate) fn screenshot_filepath() -> anyhow::Result<PathBuf> {
    let filename = OffsetDateTime::now_local()
        .context("Error obtaning local time")?
        .format(FILENAME_FMT)
        .context("Error formatting current time")?;
    Ok(screenshots_directory()?.join(filename))
}
