mod args;

pub use args::Args;

use radicle::storage::{ReadStorage, RepositoryInfo, SignedRefsInfo};

use crate::terminal as term;

use term::Element;

pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
    let profile = ctx.profile()?;
    let storage = &profile.storage;
    let repos = storage.repositories()?;
    let policy = profile.policies()?;
    let mut table = term::Table::new(term::TableOptions::bordered());
    let mut rows = Vec::new();

    if repos.is_empty() {
        return Ok(());
    }

    for RepositoryInfo {
        rid,
        head,
        doc,
        refs,
        ..
    } in repos
    {
        if doc.is_public() && args.private {
            continue;
        }
        if !doc.is_public() && args.public {
            continue;
        }
        if matches!(refs, SignedRefsInfo::None) && !args.all && !args.seeded {
            continue;
        }
        let seeded = policy.is_seeding(&rid)?;

        if !seeded && !args.all {
            continue;
        }
        if !seeded && args.seeded {
            continue;
        }
        let proj = match doc.project() {
            Ok(p) => p,
            Err(e) => {
                log::error!(target: "cli", "Error loading project payload for {rid}: {e}");
                continue;
            }
        };
        let head = term::format::oid(head).into();

        rows.push([
            term::format::bold(proj.name().to_owned()),
            term::format::tertiary(rid.urn()),
            if seeded {
                term::format::visibility(doc.visibility()).into()
            } else {
                term::format::dim("local").into()
            },
            term::format::secondary(head),
            term::format::italic(proj.description().to_owned()),
        ]);
    }
    rows.sort();

    if rows.is_empty() {
        term::println(term::format::italic("Nothing to show."));
    } else {
        table.header([
            "Name".into(),
            "RID".into(),
            "Visibility".into(),
            "Head".into(),
            "Description".into(),
        ]);
        table.divider();
        table.extend(rows);
        table.print();
    }

    Ok(())
}
