//! Matrix bot integration for Story Kit.
//!
//! When a `.huskies/bot.toml` file is present with `enabled = true`, the
//! server spawns a Matrix bot that:
//!
//! 1. Connects to the configured homeserver and joins the configured room.
//! 2. Listens for messages from other users in the room.
//! 3. Passes each message to Claude Code (the same provider as the web UI),
//!    which has native access to Story Kit MCP tools.
//! 4. Posts Claude Code's response back to the room.
//!
//! The bot is optional — if `bot.toml` is missing or `enabled = false`, the
//! server starts normally with no Matrix connection.
//!
//! Multi-room support: configure `room_ids = ["!room1:…", "!room2:…"]` in
//! `bot.toml`. Each room maintains its own independent conversation history.

/// Auto-assign handler — listens for pipeline events and assigns stories to free agents.
pub mod assign;
mod bot;
/// Cleanup worktrees command — removes stale worktrees for completed or archived stories.
pub mod cleanup_worktrees;
/// Matrix bot command handlers — parses and routes bot commands from Matrix messages.
pub mod commands;
/// `compact` command — distills the session transcript into a seed and resets, Matrix-specific glue.
pub mod compact;
pub(crate) mod config;
/// Story deletion command — handles `!delete` bot commands to remove work items.
pub mod delete;
/// `health` chat command — surface gateway, sled, matrix, creds, and build-hash status.
pub mod health;
/// htop-style agent monitor command — renders a live process table in Matrix.
pub mod htop;
/// `new project <name>` chat command — Phase 1 gateway project bootstrap.
pub mod new_project;
/// `project-rebuild <name>` chat command — rebuild Docker image, swap container, preserve state.
pub mod project_rebuild;
/// `projects` chat command — list all registered gateway projects.
pub mod projects;
/// `pull <channel>` gateway chat command — fetch, verify, and install a
/// signed release-channel artifact into the gateway's artifact store.
pub mod pull;
/// `rebuild gateway` command parsing (gateway self-rebuild).
pub mod rebuild;
/// `release` gateway chat command — build the sled binary and publish it.
pub mod release;
/// Reset command — handles `!reset` bot commands to restart the server state.
pub mod reset;
/// rmtree command — handles `!rmtree` bot commands to remove worktrees.
pub mod rmtree;
/// `upgrade [<project>]` gateway chat command — streaming per-sled binary upgrade.
pub mod sled_upgrade;
/// Start command — handles `!start` bot commands to launch agents on stories.
pub mod start;
/// Matrix `ChatTransport` implementation wrapping the Matrix SDK client.
pub mod transport_impl;

pub use bot::{ConversationEntry, ConversationRole, RoomConversation};
pub use config::BotConfig;

use crate::io::watcher::WatcherEvent;
use crate::rebuild::ShutdownReason;
use crate::service::timer::TimerStore;
use crate::services::Services;
use std::path::Path;
use std::sync::Arc;
use tokio::sync::{RwLock, broadcast, watch};

/// Attempt to start the Matrix bot.
///
/// Reads the bot configuration from `.huskies/bot.toml`. If the file is
/// absent or `enabled = false`, this function returns immediately without
/// spawning anything — the server continues normally.
///
/// When the bot is enabled, a notification listener is also spawned that
/// posts stage-transition messages to all configured rooms whenever a work
/// item moves between pipeline stages.
///
/// `services` is the shared services bundle containing the agent pool,
/// permission plumbing, and bot identity. The bot accesses these via
/// `Arc<Services>` rather than holding its own copies.
///
/// `shutdown_rx` is a watch channel that delivers a `ShutdownReason` when the
/// server is about to stop (SIGINT/SIGTERM or rebuild).  The bot uses this to
/// announce the shutdown to all configured rooms before the process exits.
///
/// Must be called from within a Tokio runtime context (e.g., from `main`).
///
/// Returns an [`tokio::task::AbortHandle`] if the bot was actually spawned (Matrix/Discord
/// transports), or `None` if the config is absent, disabled, or uses a webhook-based
/// transport (Slack/WhatsApp) that does not require a persistent background task.
#[allow(clippy::too_many_arguments)]
pub fn spawn_bot(
    project_root: &Path,
    watcher_tx: broadcast::Sender<WatcherEvent>,
    services: Arc<Services>,
    shutdown_rx: watch::Receiver<Option<ShutdownReason>>,
    gateway_active_project: Option<Arc<RwLock<String>>>,
    gateway_projects_store: Option<
        Arc<
            RwLock<
                std::collections::BTreeMap<String, crate::service::gateway::config::ProjectEntry>,
            >,
        >,
    >,
    timer_store: Arc<TimerStore>,
    gateway_event_rx: Option<
        tokio::sync::broadcast::Receiver<crate::service::gateway::GatewayStatusEvent>,
    >,
    gateway_port: Option<u16>,
    gateway_channels_store: Option<
        Arc<
            RwLock<
                std::collections::BTreeMap<
                    String,
                    crate::service::gateway::config::ReleaseChannelConfig,
                >,
            >,
        >,
    >,
) -> Option<tokio::task::AbortHandle> {
    let config = match BotConfig::load(project_root) {
        Some(c) => c,
        None => {
            crate::slog!("[matrix-bot] bot.toml absent or disabled; Matrix integration skipped");
            return None;
        }
    };

    // WhatsApp and Slack transports are handled via HTTP webhooks, not the Matrix sync loop.
    if config.transport == "whatsapp" || config.transport == "slack" {
        crate::slog!(
            "[bot] transport={} — skipping Matrix bot; webhooks handle this transport",
            config.transport
        );
        return None;
    }

    crate::slog!(
        "[matrix-bot] Starting Matrix bot → homeserver={} rooms={:?}",
        config.homeserver.as_deref().unwrap_or("(none)"),
        config.effective_room_ids()
    );

    let watcher_rx = watcher_tx.subscribe();
    let watcher_rx_auto = watcher_tx.subscribe();
    let handle = tokio::spawn(async move {
        if let Err(e) = bot::run_bot(
            config,
            services,
            watcher_rx,
            watcher_rx_auto,
            watcher_tx,
            shutdown_rx,
            gateway_active_project,
            gateway_projects_store,
            timer_store,
            gateway_event_rx,
            gateway_port,
            gateway_channels_store,
        )
        .await
        {
            crate::slog!("[matrix-bot] Fatal error: {e}");
        }
    });
    Some(handle.abort_handle())
}
