#![cfg_attr(
    not(test),
    deny(clippy::unwrap_used, clippy::panic, clippy::indexing_slicing)
)]
//! `org-gdocs` — publish a projection of an org-mode document to Google Docs and
//! sync reviewer comments back into the org file.
//!
//! Org-mode is the single source of truth; Google Docs is a collaboration surface
//! for comments only. This crate owns all testable logic (org projection, the
//! Google API client, comment anchoring, file writeback); the companion Emacs
//! package is a thin shell over the binary.
//!
//! See `docs/plans/org-gdocs.md` for the architecture and invariants this crate
//! is built against.

pub mod auth;
pub mod clean;
pub mod cli;
pub mod comments;
pub mod comments_meta;
pub mod config;
pub mod custom_id;
pub mod doctor;
pub mod envelope;
pub mod error;
pub mod google;
pub mod open;
pub mod orgfile;
pub mod project;
pub mod pull;
pub mod push;
pub mod sexp;
pub mod syncstate;

pub use error::{Error, Result};

use tftio_cli_common::{
    AgentCapability, AgentSurfaceSpec, CommandSelector, LicenseType, ToolSpec, workspace_tool,
};

const PUSH_COMMAND: CommandSelector = CommandSelector::new(&["push"]);
const PULL_COMMAND: CommandSelector = CommandSelector::new(&["pull"]);
const CLEAN_COMMAND: CommandSelector = CommandSelector::new(&["clean"]);
const OPEN_COMMAND: CommandSelector = CommandSelector::new(&["open"]);

const PUSH_CAPABILITY: AgentCapability =
    AgentCapability::minimal("push-projection", &[PUSH_COMMAND], &[])
        .with_when_to_use(
            "the user wants to publish an org file's projection to its linked Google Doc (creating the doc on first push)",
        )
        .with_when_not_to_use("the user wants to retrieve reviewer comments (use pull instead)");

const PULL_CAPABILITY: AgentCapability =
    AgentCapability::minimal("pull-comments", &[PULL_COMMAND], &[])
        .with_when_to_use(
            "the user wants to fetch reviewer comments from the linked Google Doc into the org file's metadata section",
        )
        .with_when_not_to_use("the user wants to publish content to Google Docs (use push instead)");

const CLEAN_CAPABILITY: AgentCapability =
    AgentCapability::minimal("clean-comments", &[CLEAN_COMMAND], &[])
        .with_when_to_use("the user wants to archive comments already marked DONE in the org file")
        .with_when_not_to_use("the user wants to resolve comments in Google Docs (push does that)");

const OPEN_CAPABILITY: AgentCapability = AgentCapability::minimal("open-doc", &[OPEN_COMMAND], &[])
    .with_when_to_use("the user wants the browser URL of the org file's linked Google Doc")
    .with_when_not_to_use("the org file has not yet been pushed to a Google Doc");

const AGENT_SURFACE: AgentSurfaceSpec = AgentSurfaceSpec::new(&[
    PUSH_CAPABILITY,
    PULL_CAPABILITY,
    CLEAN_CAPABILITY,
    OPEN_CAPABILITY,
]);

/// Shared CLI metadata for the `org-gdocs` binary.
pub const TOOL_SPEC: ToolSpec = workspace_tool(
    "org-gdocs",
    "org-gdocs",
    env!("CARGO_PKG_VERSION"),
    LicenseType::MIT,
    true,
    true,
)
.with_agent_surface(&AGENT_SURFACE);
