//! Local thumbnail cache.
//!
//! Feed thumbnails are remote `ytimg.com` URLs. Offline — the whole point of
//! this app — those fail to load and the feed becomes a wall of broken images.
//! So every thumbnail we learn about gets mirrored to disk.

use std::path::{Path, PathBuf};

pub fn cache_dir(app_data: &Path) -> PathBuf {
    app_data.join("thumbs")
}

/// Downloads one thumbnail if it isn't already cached. Returns its path.
pub async fn cache_one(
    client: &reqwest::Client,
    video_id: &str,
    url: &str,
    dir: &Path,
) -> Result<PathBuf, String> {
    let dest = dir.join(format!("{video_id}.jpg"));
    if dest.exists() {
        return Ok(dest);
    }

    tokio::fs::create_dir_all(dir)
        .await
        .map_err(|e| format!("Cannot create thumbnail cache dir: {e}"))?;

    let resp = client
        .get(url)
        .send()
        .await
        .map_err(|e| format!("Thumbnail request failed: {e}"))?;

    if !resp.status().is_success() {
        return Err(format!("Thumbnail returned HTTP {}", resp.status()));
    }

    let bytes = resp
        .bytes()
        .await
        .map_err(|e| format!("Cannot read thumbnail body: {e}"))?;

    // Write to a temp name then rename, so an interrupted download never leaves
    // a half-written JPEG that later looks cached.
    let tmp = dir.join(format!("{video_id}.jpg.part"));
    tokio::fs::write(&tmp, &bytes)
        .await
        .map_err(|e| format!("Cannot write thumbnail: {e}"))?;
    tokio::fs::rename(&tmp, &dest)
        .await
        .map_err(|e| format!("Cannot finalize thumbnail: {e}"))?;

    Ok(dest)
}
