//! Phase 3: publish a final video to the Adom Wiki.
//!
//! Pushes the polished demo video into the wiki page's repo via
//! `adom-wiki repo push --files <video> <org/slug> -m "<msg>"`. Binaries push
//! fine: the mp4 lands in the page's Files tab and serves at
//! `https://wiki.adom.inc/api/v1/pages/<slug>/files/<file>`, which is the URL we
//! return so callers can embed it.
//!
//! (The old `adom-wiki asset upload` pillar this used to wrap was removed; the
//! CLI no longer has an `asset` command. For versioned media,
//! `adom-wiki release upload <ref> <ver> <file>` exists, but for a page demo
//! video `repo push` is the right call.)

use std::process::Command;

const WIKI_BASE: &str = "https://wiki.adom.inc";

pub struct PublishConfig {
    pub input: std::path::PathBuf,
    pub page: String,
    pub caption: Option<String>,
    pub asset_type: String,
}

pub fn run(cfg: PublishConfig) -> Result<String, String> {
    if !cfg.input.exists() {
        return Err(format!(
            "input video not found: {}. Hint: produce it via `adom-video-post voiceover` first.",
            cfg.input.display()
        ));
    }

    // Validate page-ref shape: <owner>/<slug> (e.g. adom/adom-desktop-fusion-bridge).
    let (_owner, slug) = parse_page_ref(&cfg.page)?;

    // Validate file extension against the asset type.
    let ext = cfg
        .input
        .extension()
        .and_then(|e| e.to_str())
        .unwrap_or("")
        .to_lowercase();
    let valid_video_exts = ["webm", "mp4", "mov", "mkv"];
    let valid_image_exts = ["png", "jpg", "jpeg"];
    let is_video = valid_video_exts.contains(&ext.as_str());
    let is_image = valid_image_exts.contains(&ext.as_str());

    if cfg.asset_type == "video" && !is_video {
        return Err(format!(
            "input file '{}' is not a recognized video format ({:?}). Hint: pass --asset-type screenshot if uploading a still image.",
            cfg.input.display(),
            valid_video_exts
        ));
    }
    if cfg.asset_type == "screenshot" && !is_image {
        return Err(format!(
            "input file '{}' is not a recognized image format ({:?}).",
            cfg.input.display(),
            valid_image_exts
        ));
    }

    // Check adom-wiki is installed.
    if which("adom-wiki").is_none() {
        return Err(
            "adom-wiki CLI not found in PATH. Hint: it ships with every Adom container. Run `which adom-wiki` to verify, or contact your container admin."
                .to_string(),
        );
    }

    let filename = cfg
        .input
        .file_name()
        .and_then(|f| f.to_str())
        .ok_or_else(|| format!("could not read filename from {}", cfg.input.display()))?;

    let message = match &cfg.caption {
        Some(c) => format!("Add {} demo {}: {}", cfg.asset_type, filename, c),
        None => format!("Add {} {} via video-post publish", cfg.asset_type, filename),
    };

    // Build the push command: adom-wiki repo push --files <input> <page> -m "<msg>"
    let mut cmd = Command::new("adom-wiki");
    cmd.arg("repo").arg("push");
    cmd.arg("--files").arg(&cfg.input);
    cmd.args(["-m", &message]);
    cmd.arg(&cfg.page);

    println!("uploading {} to wiki page {}...", cfg.input.display(), cfg.page);

    let result = cmd.output().map_err(|e| format!("adom-wiki spawn failed: {}", e))?;
    if !result.status.success() {
        let stderr = String::from_utf8_lossy(&result.stderr);
        let stdout = String::from_utf8_lossy(&result.stdout);
        return Err(format!(
            "adom-wiki repo push failed:\n{}{}",
            stdout, stderr
        ));
    }

    // The served URL is deterministic: <base>/api/v1/pages/<slug>/files/<file>.
    Ok(served_file_url(slug, filename))
}

/// Parse a page ref of the form `<owner>/<slug>` and return (owner, slug).
/// The served file URL keys off the slug only (the last path segment).
fn parse_page_ref(page: &str) -> Result<(&str, &str), String> {
    let mut parts = page.splitn(2, '/');
    let owner = parts.next().unwrap_or("");
    let slug = parts.next().unwrap_or("");
    if owner.is_empty() || slug.is_empty() || slug.contains('/') {
        return Err(format!(
            "invalid --page '{}': expected format <owner>/<slug> like adom/adom-desktop-fusion-bridge, adom/symbol-creator. Hint: browse pages at {}.",
            page, WIKI_BASE
        ));
    }
    Ok((owner, slug))
}

/// Build the URL the pushed file serves at, e.g.
/// https://wiki.adom.inc/api/v1/pages/adom-desktop-fusion-bridge/files/library-demo.mp4
fn served_file_url(slug: &str, filename: &str) -> String {
    format!("{}/api/v1/pages/{}/files/{}", WIKI_BASE, slug, filename)
}

fn which(cmd: &str) -> Option<std::path::PathBuf> {
    let path = std::env::var_os("PATH")?;
    for dir in std::env::split_paths(&path) {
        let candidate = dir.join(cmd);
        if candidate.is_file() {
            return Some(candidate);
        }
    }
    None
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn parses_owner_and_slug() {
        let (owner, slug) = parse_page_ref("adom/adom-desktop-fusion-bridge").unwrap();
        assert_eq!(owner, "adom");
        assert_eq!(slug, "adom-desktop-fusion-bridge");
    }

    #[test]
    fn rejects_missing_slug() {
        assert!(parse_page_ref("adom").is_err());
        assert!(parse_page_ref("").is_err());
        assert!(parse_page_ref("/slug").is_err());
        assert!(parse_page_ref("a/b/c").is_err());
    }

    #[test]
    fn builds_served_url_from_slug_only() {
        assert_eq!(
            served_file_url("adom-desktop-fusion-bridge", "library-demo.mp4"),
            "https://wiki.adom.inc/api/v1/pages/adom-desktop-fusion-bridge/files/library-demo.mp4"
        );
    }
}