//! MCP freeze and unfreeze tools — thin adapters over `service::work_item::freeze`.

use crate::http::context::AppContext;
use crate::service::work_item::{FreezeStatus, UnfreezeStatus};
use serde_json::Value;

/// Freeze a work item, suppressing pipeline advancement and auto-assign.
///
/// Accepts a `story_id` (full filename stem, e.g. `"42_story_foo"`) and
/// delegates to [`service::work_item::freeze::freeze`].
pub(crate) fn tool_freeze_story(args: &Value, _ctx: &AppContext) -> Result<String, String> {
    let req = crate::validation::FreezeStoryRequest::from_json(args)?;
    let story_id = req.story_id.as_str();

    match crate::service::work_item::freeze::freeze(story_id)? {
        FreezeStatus::AlreadyFrozen => Ok(format!("Story '{story_id}' is already frozen.")),
        FreezeStatus::Frozen => Ok(format!(
            "Frozen story '{story_id}'. Pipeline advancement and auto-assign suppressed until unfrozen."
        )),
    }
}

/// Unfreeze a work item, resuming normal pipeline behaviour.
///
/// Accepts a `story_id` (full filename stem, e.g. `"42_story_foo"`) and
/// delegates to [`service::work_item::freeze::unfreeze`].
pub(crate) fn tool_unfreeze_story(args: &Value, _ctx: &AppContext) -> Result<String, String> {
    let req = crate::validation::FreezeStoryRequest::from_json(args)?;
    let story_id = req.story_id.as_str();

    match crate::service::work_item::freeze::unfreeze(story_id)? {
        UnfreezeStatus::NotFrozen => Ok(format!(
            "Story '{story_id}' is not frozen. Nothing to unfreeze."
        )),
        UnfreezeStatus::Unfrozen => Ok(format!(
            "Unfrozen story '{story_id}'. Normal pipeline behaviour resumed."
        )),
    }
}

// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------

#[cfg(test)]
mod tests {
    use super::*;
    use crate::http::test_helpers::test_ctx;
    use serde_json::json;

    #[test]
    fn tool_freeze_story_freezes_item() {
        crate::crdt_state::init_for_test();
        let story_id = "8790_story_mcp_freeze_tool";
        crate::db::write_item_with_content(
            story_id,
            "2_current",
            "---\nname: MCP Freeze Tool Test\n---\n",
            crate::db::ItemMeta::named("MCP Freeze Tool Test"),
        );

        let tmp = tempfile::tempdir().unwrap();
        let ctx = test_ctx(tmp.path());
        let result = tool_freeze_story(&json!({"story_id": story_id}), &ctx);
        assert!(result.is_ok(), "freeze tool should succeed: {result:?}");
        assert!(
            result.unwrap().contains("Frozen"),
            "response should mention frozen"
        );

        let item = crate::pipeline_state::read_typed(story_id)
            .expect("read_typed should succeed")
            .expect("item should be present");
        assert!(
            matches!(item.stage, crate::pipeline_state::Stage::Frozen { .. }),
            "stage should be frozen after MCP freeze"
        );
    }

    #[test]
    fn tool_unfreeze_story_unfreezes_item() {
        crate::crdt_state::init_for_test();
        let story_id = "8791_story_mcp_unfreeze_tool";
        crate::db::write_item_with_content(
            story_id,
            "2_current",
            "---\nname: MCP Unfreeze Tool Test\n---\n",
            crate::db::ItemMeta::named("MCP Unfreeze Tool Test"),
        );

        let tmp = tempfile::tempdir().unwrap();
        let ctx = test_ctx(tmp.path());

        // Freeze first.
        tool_freeze_story(&json!({"story_id": story_id}), &ctx).unwrap();

        let result = tool_unfreeze_story(&json!({"story_id": story_id}), &ctx);
        assert!(result.is_ok(), "unfreeze tool should succeed: {result:?}");
        assert!(
            result.unwrap().contains("Unfrozen"),
            "response should mention unfrozen"
        );

        let item = crate::pipeline_state::read_typed(story_id)
            .expect("read_typed should succeed")
            .expect("item should be present");
        assert!(
            !matches!(item.stage, crate::pipeline_state::Stage::Frozen { .. }),
            "stage should not be frozen after MCP unfreeze"
        );
    }

    #[test]
    fn tool_freeze_story_missing_story_id_returns_error() {
        let tmp = tempfile::tempdir().unwrap();
        let ctx = test_ctx(tmp.path());
        let result = tool_freeze_story(&json!({}), &ctx);
        assert!(result.is_err(), "missing story_id should return Err");
        assert!(
            result.unwrap_err().contains("story_id"),
            "error should mention story_id"
        );
    }
}
