"""
Tests for Phase 25: Swarm Blueprints & Brynq Exchange.
"""

import json
from pathlib import Path

import pytest


@pytest.fixture(autouse=True)
def _isolate(tmp_path, monkeypatch):
    """Redirect all storage to temp directory."""
    channels = tmp_path / "channels"
    sessions = tmp_path / "sessions"
    cursors = tmp_path / "cursors"
    tasks = tmp_path / "tasks"
    blueprints = tmp_path / "blueprints"
    deps = tmp_path / "task_dependencies"

    for d in (channels, sessions, cursors, tasks, blueprints, deps):
        d.mkdir(parents=True, exist_ok=True)

    import brynq.server as srv
    monkeypatch.setattr(srv, "BROKER_DIR", tmp_path)
    monkeypatch.setattr(srv, "CHANNELS_DIR", channels)
    monkeypatch.setattr(srv, "SESSIONS_DIR", sessions)
    monkeypatch.setattr(srv, "CURSORS_DIR", cursors)

    import brynq.tasks as t
    monkeypatch.setattr(t, "BROKER_DIR", tmp_path)
    monkeypatch.setattr(t, "TASKS_DIR", tasks)
    monkeypatch.setattr(t, "CHANNELS_DIR", channels)

    import brynq.blueprints as bp
    monkeypatch.setattr(bp, "BLUEPRINTS_DIR", blueprints)


def test_publish_and_get_blueprint():
    from brynq.blueprints import publish_blueprint, get_blueprint
    bp_def = {
        "name": "SEO Swarm",
        "version": "1.0",
        "agents": [{"role": "writer"}],
        "tasks": [{"id": "t1", "description": "Write article"}],
    }
    published = publish_blueprint(bp_def)
    assert "blueprint_id" in published
    assert published["deploy_count"] == 0

    retrieved = get_blueprint(published["blueprint_id"])
    assert retrieved is not None
    assert retrieved["name"] == "SEO Swarm"


def test_invalid_blueprint():
    from brynq.blueprints import publish_blueprint
    with pytest.raises(ValueError):
        publish_blueprint({"name": "Bad"})


def test_list_blueprints():
    from brynq.blueprints import publish_blueprint, list_blueprints
    publish_blueprint({"name": "A", "version": "1", "agents": [], "tasks": []})
    publish_blueprint({"name": "B", "version": "1", "agents": [], "tasks": []})
    all_bps = list_blueprints()
    assert len(all_bps) == 2


def test_delete_blueprint():
    from brynq.blueprints import publish_blueprint, delete_blueprint, get_blueprint
    pub = publish_blueprint({"name": "X", "version": "1", "agents": [], "tasks": []})
    bp_id = pub["blueprint_id"]
    assert delete_blueprint(bp_id) is True
    assert get_blueprint(bp_id) is None


def test_delete_nonexistent():
    from brynq.blueprints import delete_blueprint
    assert delete_blueprint("nope") is False


def test_deploy_blueprint():
    from brynq.blueprints import publish_blueprint, deploy_blueprint, get_blueprint
    bp_def = {
        "name": "QA Swarm",
        "version": "1.0",
        "agents": [{"role": "tester", "capabilities": ["python"]}],
        "tasks": [
            {"id": "test1", "title": "Run tests", "description": "Execute test suite"},
            {"id": "report1", "title": "Report", "description": "Generate report", "dependencies": ["test1"]},
        ],
    }
    published = publish_blueprint(bp_def)
    result = deploy_blueprint(published["blueprint_id"], channel="test_chan")
    assert result["status"] == "deployed"
    assert len(result["tasks_created"]) == 2

    # deploy_count should increment
    updated = get_blueprint(published["blueprint_id"])
    assert updated["deploy_count"] == 1


def test_deploy_nonexistent():
    from brynq.blueprints import deploy_blueprint
    with pytest.raises(ValueError):
        deploy_blueprint("nope")


def test_validate_blueprint():
    from brynq.blueprints import validate_blueprint
    assert validate_blueprint({"name": "X", "version": "1", "agents": [], "tasks": []}) is True
    assert validate_blueprint({"name": "X"}) is False
    assert validate_blueprint({"name": "X", "version": "1", "agents": "bad", "tasks": []}) is False
