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

use crate::{config::Config, error::AppError};

pub fn resolve(config: &Config, relative: &str) -> Result<PathBuf, AppError> {
    let relative = Path::new(relative);
    if relative.is_absolute()
        || relative
            .components()
            .any(|part| !matches!(part, Component::Normal(_)))
    {
        return Err(AppError::bad_request("invalid media path"));
    }

    let candidate = config.media_root.join(relative);
    let canonical = candidate
        .canonicalize()
        .map_err(|_| AppError::not_found("media path not found"))?;
    if !canonical.starts_with(&config.media_root) {
        return Err(AppError::bad_request("media path escapes the library"));
    }
    Ok(canonical)
}

pub fn relative(config: &Config, absolute: &Path) -> Result<String, AppError> {
    absolute
        .strip_prefix(&config.media_root)
        .map(|path| path.to_string_lossy().replace('\\', "/"))
        .map_err(AppError::internal)
}
