//! Watcher event types emitted to WebSocket clients and internal subscribers.

use serde::Serialize;

/// A lifecycle event emitted by the filesystem watcher.
#[derive(Clone, Debug, Serialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum WatcherEvent {
    /// A work-pipeline file was created, modified, or deleted.
    WorkItem {
        /// Pipeline stage directory (e.g. `"2_current"`, `"5_archived"`).
        stage: String,
        /// Work item ID (filename stem without extension, e.g. `"42_story_my_feature"`).
        item_id: String,
        /// Semantic action inferred from the stage (e.g. `"start"`, `"accept"`).
        action: String,
        /// The deterministic git commit message used (or that would have been used).
        commit_msg: String,
        /// The pipeline stage the item moved FROM, populated for move operations.
        /// `None` for creations, deletions, or synthetic events.
        from_stage: Option<String>,
    },
    /// `.huskies/project.toml` was modified at the project root (not inside a worktree).
    ConfigChanged,
    /// An agent's state changed (started, stopped, completed, etc.).
    /// Triggers a pipeline state refresh so the frontend can update agent
    /// assignments without waiting for a filesystem event.
    AgentStateChanged,
    /// A story encountered a failure (e.g. merge failure).
    /// Triggers an error notification to configured Matrix rooms.
    MergeFailure {
        /// Work item ID (e.g. `"42_story_my_feature"`).
        story_id: String,
        /// Human-readable description of the failure.
        reason: String,
    },
    /// An agent hit an API rate limit.
    /// Triggers a warning notification to configured chat rooms.
    RateLimitWarning {
        /// Work item ID the agent is working on.
        story_id: String,
        /// Name of the agent that hit the rate limit.
        agent_name: String,
    },
    /// A story has been blocked (e.g. retry limit exceeded, empty diff).
    /// Triggers a warning notification to configured chat rooms.
    StoryBlocked {
        /// Work item ID (e.g. `"42_story_my_feature"`).
        story_id: String,
        /// Human-readable reason the story was blocked.
        reason: String,
    },
    /// An agent hit a hard API rate limit and will be blocked until `reset_at`.
    /// Triggers auto-scheduling of a timer and a notification with the resume time.
    RateLimitHardBlock {
        /// Work item ID the agent is working on.
        story_id: String,
        /// Name of the agent that hit the hard rate limit.
        agent_name: String,
        /// UTC instant at which the rate limit resets.
        reset_at: chrono::DateTime<chrono::Utc>,
    },
    /// An OAuth account pool swap succeeded: a different account is now active.
    /// Triggers a notification to chat transports naming the new account.
    OAuthAccountSwapped {
        /// Email address of the newly activated account.
        new_email: String,
    },
    /// All OAuth accounts in the pool are rate-limited — no swap was possible.
    /// Triggers a notification to chat transports with the earliest reset time.
    OAuthAccountsExhausted {
        /// Human-readable message describing when the earliest reset occurs.
        earliest_reset_msg: String,
    },
    /// An agent transitioned to the Running state for a story.
    /// Triggers a status notification to configured chat rooms.
    AgentStarted {
        /// Work item ID the agent is working on.
        story_id: String,
        /// Name of the agent that started.
        agent_name: String,
    },
    /// An agent finished processing a story (gates passed or failed).
    /// Triggers a status notification to configured chat rooms.
    AgentCompleted {
        /// Work item ID the agent was working on.
        story_id: String,
        /// Name of the agent that completed.
        agent_name: String,
        /// `true` if acceptance gates passed; `false` if they failed.
        success: bool,
    },
    /// A new work item was successfully created and added to the backlog.
    /// Triggers a creation notification to configured chat rooms.
    NewItemCreated {
        /// Work item ID (e.g. `"1075_refactor_split_stage_enum"`).
        item_id: String,
        /// Human-readable item type (`"story"`, `"bug"`, `"refactor"`, `"spike"`, `"epic"`).
        item_type: String,
        /// Human-readable item name.
        name: String,
        /// Readable label for who/what created the item (e.g. `"user alice"`,
        /// `"agent coder-1@story=42"`, `"chat-bot Timmy@!room:home"`).
        origin: String,
    },
    /// A `GatesFailed` merge failure is being automatically retried after a
    /// delay, without human intervention (story 1185).
    /// Triggers a status notification to configured chat rooms.
    MergeAutoRetry {
        /// Work item ID (e.g. `"42_story_my_feature"`).
        story_id: String,
        /// This retry's attempt number (1-based).
        attempt: u32,
        /// Total auto-retry budget shared with the auto-block threshold.
        budget: u32,
    },
    /// Free disk space on the `/workspace` filesystem crossed a warn/critical
    /// threshold (story 1200).
    /// Triggers a rate-limited warning notification to configured chat rooms.
    DiskSpaceWarning {
        /// Severity level: `"warn"` or `"critical"`.
        level: String,
        /// Free space in bytes at the time of the check.
        free_bytes: u64,
        /// Size of the `target/` directory in bytes.
        target_bytes: u64,
        /// Size of the `.huskies/worktrees/` directory in bytes.
        worktrees_bytes: u64,
        /// Identifier of the sled that observed the reading.
        host_id: String,
    },
    /// Free disk space recovered above the warn threshold plus its recovery
    /// margin, after a warn/critical warning had been sent (story 1200).
    /// Triggers a single recovery notification to configured chat rooms.
    DiskSpaceRecovered {
        /// Free space in bytes at the time of recovery.
        free_bytes: u64,
        /// Identifier of the sled that observed the recovery.
        host_id: String,
    },
}
