//! `pic files ls | get | rm` — operator-facing files inspection (G2).
//!
//! Wraps the read-only `/api/v1/admin/apps/{id}/files*` surface. There is
//! no `set`/`upload` — blob writes go through scripts (`files::create`);
//! the admin surface is inspect + delete only, matching the dashboard.

use std::io::Write;
use std::path::Path;

use anyhow::{Context, Result};

use crate::client::Client;
use crate::config;
use crate::output::{OutputMode, Table};

pub async fn ls(
    app: Option<&str>,
    group: Option<&str>,
    collection: &str,
    limit: u32,
    mode: OutputMode,
) -> Result<()> {
    let creds = config::resolve()?;
    let client = Client::from_creds(&creds)?;
    let page = match crate::cmds::require_one_owner(app, group)? {
        crate::cmds::OwnerRef::App(a) => client.files_list(a, collection, limit).await?,
        // §11.6 M4: a group's shared-files collection.
        crate::cmds::OwnerRef::Group(g) => client.group_files_list(g, collection, limit).await?,
    };
    let mut table = Table::new(["id", "name", "content_type", "size", "updated_at"]);
    for f in page.files {
        table.row([
            f.id,
            f.name,
            f.content_type,
            f.size.to_string(),
            f.updated_at,
        ]);
    }
    table.print(mode);
    if page.next_cursor.is_some() {
        let _ = writeln!(
            std::io::stderr(),
            "(more results available — raise --limit to see them)"
        );
    }
    Ok(())
}

/// Download a file's bytes. With `--out <path>` writes to disk; otherwise
/// streams raw bytes to stdout (pipe to a file or `xxd`). `--app` or `--group`.
pub async fn get(
    app: Option<&str>,
    group: Option<&str>,
    collection: &str,
    file_id: &str,
    out: Option<&Path>,
) -> Result<()> {
    let creds = config::resolve()?;
    let client = Client::from_creds(&creds)?;
    let bytes = match crate::cmds::require_one_owner(app, group)? {
        crate::cmds::OwnerRef::App(a) => client.files_get_bytes(a, collection, file_id).await?,
        crate::cmds::OwnerRef::Group(g) => {
            client.group_files_get_bytes(g, collection, file_id).await?
        }
    };
    match out {
        Some(path) => {
            std::fs::write(path, &bytes).with_context(|| format!("writing {}", path.display()))?;
            let _ = writeln!(
                std::io::stderr(),
                "Wrote {} bytes to {}",
                bytes.len(),
                path.display()
            );
        }
        None => {
            std::io::stdout()
                .write_all(&bytes)
                .context("writing bytes to stdout")?;
        }
    }
    Ok(())
}

pub async fn rm(app: &str, collection: &str, file_id: &str) -> Result<()> {
    let creds = config::resolve()?;
    let client = Client::from_creds(&creds)?;
    client.files_delete(app, collection, file_id).await?;
    println!("Deleted file {file_id} from {collection}");
    Ok(())
}
