import json

from tinybot.cowork.service import CoworkService
from tinybot.cowork.types import CoworkMailboxRecord


def test_create_session_persists_agents_threads_and_lead_inbox(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session(
        goal="Plan a research trip",
        title="Trip cowork",
        agents=[
            {
                "id": "planner",
                "name": "Planner",
                "role": "Trip planner",
                "goal": "Build the itinerary",
                "responsibilities": ["Coordinate constraints"],
            },
            {
                "id": "budget",
                "name": "Budget",
                "role": "Budget analyst",
                "goal": "Check costs",
                "responsibilities": ["Estimate costs"],
            },
        ],
        tasks=[
            {
                "id": "1",
                "title": "Draft itinerary",
                "description": "Create the first itinerary",
                "assigned_agent_id": "planner",
                "dependencies": [],
            }
        ],
    )

    assert session.id
    assert set(session.agents) == {"planner", "budget"}
    assert len(session.threads) == 1
    assert session.agents["planner"].inbox
    assert session.agents["budget"].inbox == []
    assert any(span.kind == "session" and span.name == "Session created" for span in session.trace_spans)

    reloaded = CoworkService(temp_workspace).get_session(session.id)
    assert reloaded is not None
    assert reloaded.goal == "Plan a research trip"
    assert reloaded.tasks["1"].assigned_agent_id == "planner"
    assert reloaded.trace_spans[0].kind == "session"


def test_send_message_and_mark_read(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session("Compare tools", "Tools", [], [])

    agent_ids = list(session.agents)
    sender, recipient = agent_ids[0], agent_ids[1]
    service.mark_messages_read(session, recipient)
    message = service.send_message(session, sender_id=sender, recipient_ids=[recipient], content="Please verify this.")

    assert message.id in session.agents[recipient].inbox
    unread = service.mark_messages_read(session, recipient)
    assert [m.id for m in unread] == [message.id]
    assert session.agents[recipient].inbox == []
    assert recipient in session.messages[message.id].read_by


def test_mailbox_records_persist_with_legacy_safe_defaults(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session("Persist mailbox", "Mailbox", [], [])
    agent_id = next(iter(session.agents))
    service.add_mailbox_record(
        session,
        CoworkMailboxRecord(
            id="env_test",
            sender_id="user",
            recipient_ids=[agent_id],
            content="Persist me",
            status="delivered",
            requires_reply=True,
            priority=50,
            correlation_id="corr_test",
        ),
    )

    reloaded = CoworkService(temp_workspace).get_session(session.id)

    assert reloaded is not None
    assert reloaded.mailbox["env_test"].requires_reply is True
    assert reloaded.mailbox["env_test"].priority == 50
    assert reloaded.mailbox["env_test"].correlation_id == "corr_test"


def test_complete_task_updates_session_state(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session("Write summary", "Summary", [], [])
    task_id = next(iter(session.tasks))

    result = service.complete_task(session, task_id, "Finished the initial pass.")

    assert "marked completed" in result
    assert session.tasks[task_id].status == "completed"
    assert session.status in {"active", "completed"}
    assert any(event.type == "task.completed" for event in session.events)
    assert any(span.kind == "task" and span.name == "Task completed" for span in session.trace_spans)


def test_retry_task_queues_failed_task(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session("Retry work", "Retry", [], [])
    task_id = next(iter(session.tasks))
    service.complete_task(session, task_id, "failed once", status="failed")

    result = service.retry_task(session, task_id)

    assert "queued for retry" in result
    assert session.tasks[task_id].status == "pending"
    assert session.tasks[task_id].error is None
    assert any(event.type == "task.retried" for event in session.events)
    assert any(span.kind == "task" and span.name == "Task retried" for span in session.trace_spans)


def test_request_task_review_creates_review_task(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session("Review work", "Review", [], [])
    task_id = next(iter(session.tasks))
    service.complete_task(session, task_id, "answer")

    review_task = service.request_task_review(session, task_id)

    assert not isinstance(review_task, str)
    assert review_task.dependencies == [task_id]
    assert review_task.assigned_agent_id in session.agents
    assert any(event.type == "task.review_requested" for event in session.events)
    assert any(span.kind == "review" and span.name == "Review requested" for span in session.trace_spans)


def test_complete_task_extracts_structured_result_and_shared_memory(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session("Make a decision", "Decision", [], [])
    task_id = next(iter(session.tasks))

    service.complete_task(
        session,
        task_id,
        json.dumps(
            {
                "answer": "Choose option A.",
                "findings": ["A is cheaper"],
                "risks": ["Supplier lead time"],
                "open_questions": ["Confirm final budget"],
                "confidence": 0.8,
            }
        ),
    )

    task = session.tasks[task_id]
    assert task.result_data["answer"] == "Choose option A."
    assert task.confidence == 0.8
    assert "A is cheaper" in session.shared_summary
    assert session.shared_memory["findings"][0]["text"] == "A is cheaper"
    assert session.shared_memory["risks"][0]["source_task_id"] == task_id
    assert session.shared_memory["open_questions"][0]["text"] == "Confirm final budget"
    assert "Choose option A." in session.final_draft


def test_create_session_accepts_new_cowork_modes_and_subscriptions(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session(
        "Route events",
        "Events",
        [
            {
                "id": "router",
                "name": "Router",
                "role": "Router",
                "goal": "Route",
                "responsibilities": [],
                "subscriptions": ["incident", "triage"],
            }
        ],
        [],
        workflow_mode="message_bus",
    )

    assert session.workflow_mode == "message_bus"
    assert session.agents["router"].subscriptions == ["incident", "triage"]

    fallback = service.create_session("Unknown mode", "Unknown", [], [], workflow_mode="missing")

    assert fallback.workflow_mode == "adaptive_starter"


def test_canonical_architecture_names_and_legacy_alias_load(temp_workspace):
    service = CoworkService(temp_workspace)
    default_session = service.create_session("Clarify goal", "Default", [], [])
    legacy_input = service.create_session("Legacy input", "Legacy", [], [], workflow_mode="hybrid")

    assert default_session.workflow_mode == "adaptive_starter"
    assert legacy_input.workflow_mode == "adaptive_starter"
    assert service.workflow_profile("adaptive_starter") == "hybrid"
    assert service.architecture_policy("hybrid").architecture == "adaptive_starter"
    assert service.architecture_policy("swarm").architecture == "swarm"

    reloaded = CoworkService(temp_workspace).get_session(legacy_input.id)
    assert reloaded is not None
    assert reloaded.workflow_mode == "adaptive_starter"


def test_round_progress_tracks_convergence(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session("Converge", "Converge", [], [])
    before = service.progress_signature(session)

    assert service.record_round_progress(session, before) is False
    assert session.no_progress_rounds == 1
    assert service.record_round_progress(session, service.progress_signature(session)) is False
    assert service.convergence_reached(session) is True
    assert service.assess_session(session)["next_action"] == "review_convergence"


def test_loads_minimal_legacy_store_payload(temp_workspace):
    store_dir = temp_workspace / "cowork"
    store_dir.mkdir()
    (store_dir / "store.json").write_text(
        json.dumps(
            {
                "version": 1,
                "sessions": [
                    {
                        "id": "cw_legacy",
                        "title": "Legacy",
                        "goal": "Keep old payloads readable",
                        "agents": {
                            "agent": {
                                "id": "agent",
                                "name": "Agent",
                                "role": "Reviewer",
                                "goal": "Review",
                            }
                        },
                        "tasks": {},
                        "threads": {},
                        "messages": {},
                        "events": [],
                    }
                ],
            }
        ),
        encoding="utf-8",
    )

    session = CoworkService(temp_workspace).get_session("cw_legacy")

    assert session is not None
    assert session.agents["agent"].status == "idle"
    assert session.agents["agent"].current_task_title is None


def test_loads_legacy_hybrid_store_as_adaptive_starter(temp_workspace):
    store_dir = temp_workspace / "cowork"
    store_dir.mkdir()
    (store_dir / "store.json").write_text(
        json.dumps(
            {
                "version": 1,
                "sessions": [
                    {
                        "id": "cw_hybrid",
                        "title": "Legacy Hybrid",
                        "goal": "Keep old mode readable",
                        "workflow_mode": "hybrid",
                        "agents": {},
                        "tasks": {},
                        "threads": {},
                        "messages": {},
                        "events": [],
                    }
                ],
            }
        ),
        encoding="utf-8",
    )

    session = CoworkService(temp_workspace).get_session("cw_hybrid")

    assert session is not None
    assert session.workflow_mode == "adaptive_starter"


def test_legacy_session_loads_with_default_branch(temp_workspace):
    store_dir = temp_workspace / "cowork"
    store_dir.mkdir()
    (store_dir / "store.json").write_text(
        json.dumps(
            {
                "version": 1,
                "sessions": [
                    {
                        "id": "cw_branchless",
                        "title": "Branchless",
                        "goal": "Migrate branchless payload",
                        "workflow_mode": "hybrid",
                        "agents": {},
                        "tasks": {},
                        "threads": {},
                        "messages": {},
                        "events": [],
                    }
                ],
            }
        ),
        encoding="utf-8",
    )

    session = CoworkService(temp_workspace).get_session("cw_branchless")

    assert session is not None
    assert session.current_branch_id == "default"
    assert session.branches["default"].architecture == "adaptive_starter"
    assert session.branches["default"].status == "active"


def test_derive_branch_preserves_source_stage_record_and_allows_selection(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session("Investigate architecture", "Architecture", [], [])
    service.complete_task(session, next(iter(session.tasks)), "Useful result")

    branch = service.derive_branch(
        session,
        target_architecture="swarm",
        reason="Need horizontal exploration",
        inherited_context_summary="Carry only the organized result.",
    )

    assert not isinstance(branch, str)
    assert branch.source_branch_id == "default"
    assert branch.architecture == "swarm"
    assert session.current_branch_id == branch.id
    assert session.branches["default"].status in {"active", "completed"}
    assert session.stage_records[-1].target_branch_id == branch.id
    assert session.stage_records[-1].inherited_context_summary == "Carry only the organized result."
    assert all("private_summary" not in ref for ref in session.stage_records[-1].message_refs)

    selected = service.select_branch(session, "default")

    assert not isinstance(selected, str)
    assert session.current_branch_id == "default"
    assert session.workflow_mode == "adaptive_starter"


def test_branch_result_selection_is_explicit_and_not_replaced_by_newer_branch(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session("Answer with branches", "Branches", [], [])

    service.complete_task(session, next(iter(session.tasks)), "Default branch answer")
    default_result = session.branches["default"].branch_result

    assert default_result is not None
    assert session.session_final_result is None

    selected = service.select_session_final_result(session, "default")

    assert not isinstance(selected, str)
    assert selected.selected_branch_id == "default"
    assert selected.selected_result_id == default_result.id

    branch = service.derive_branch(session, target_architecture="swarm", reason="Try another answer")

    assert not isinstance(branch, str)
    derived_task = service.add_task(
        session,
        title="Derived synthesis",
        description="Produce a derived branch answer",
        assigned_agent_id=service.lead_agent_id(session),
    )
    service.complete_task(session, derived_task.id, "Derived branch answer")

    assert session.branches[branch.id].branch_result is not None
    assert session.session_final_result is not None
    assert session.session_final_result.selected_branch_id == "default"
    assert session.session_final_result.selected_result_id == default_result.id


def test_branch_merge_creates_candidate_final_result_from_multiple_branch_results(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session("Merge branches", "Merge", [], [])

    service.complete_task(session, next(iter(session.tasks)), "Default result")
    branch = service.derive_branch(session, target_architecture="agent_team", reason="Compare result")

    assert not isinstance(branch, str)
    derived_task = service.add_task(
        session,
        title="Derived result",
        description="Produce another result",
        assigned_agent_id=service.lead_agent_id(session),
    )
    service.complete_task(session, derived_task.id, "Derived result")

    merged = service.merge_branch_results(session, ["default", branch.id], summary="Merged candidate")

    assert not isinstance(merged, str)
    assert merged.source == "branch_merge"
    assert merged.source_branch_ids == ["default", branch.id]
    assert merged.summary == "Merged candidate"
    assert session.session_final_result == merged


def test_agent_delegation_creates_parent_scoped_sub_agent_with_brief(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session(
        "Delegate bounded research",
        "Delegation",
        [{"id": "lead", "name": "Lead", "role": "Coordinator", "goal": "Coordinate"}],
        [],
        workflow_mode="agent_team",
        budgets={"max_spawned_agents": 2, "parallel_width": 2},
    )

    created = service.request_agent_delegation(
        session,
        parent_agent_id="lead",
        task_goal="Inspect only the supplied artifact references.",
        constraints=["Do not read parent private context."],
        input_references=[{"type": "artifact", "ref": "artifact://summary", "summary": "Prepared summary"}],
        expected_output="Answer with cited evidence.",
        tools=["cowork_internal", "read_file"],
        stopping_criteria=["Return result to parent."],
    )

    assert not isinstance(created, str)
    sub_agent = created["sub_agent"]
    brief = created["brief"]
    delegated = created["delegated_task"]
    assert sub_agent.parent_agent_id == "lead"
    assert sub_agent.lifetime == "temporary"
    assert sub_agent.sub_agent_scope == "parent"
    assert sub_agent.delegated_task_id == delegated.id
    assert sub_agent.delegated_brief_id == brief.id
    assert brief.task_goal == "Inspect only the supplied artifact references."
    assert brief.input_references == [{"ref": "artifact://summary", "type": "artifact", "summary": "Prepared summary"}]
    assert "private_summary" not in brief.__dict__
    assert delegated.status == "active"
    assert delegated.scope == "parent"
    assert session.isolated_sub_agent_contexts[sub_agent.isolated_context_id].brief_id == brief.id
    assert (
        service.architecture_policy(session.workflow_mode)
        .topology(session)
        .payload["metadata"]["delegated_tasks"][0]["id"]
        == delegated.id
    )


def test_delegation_guardrails_filter_context_tools_and_budgets(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session(
        "Guard delegation",
        "Guardrails",
        [{"id": "lead", "name": "Lead", "role": "Coordinator", "goal": "Coordinate"}],
        [],
        workflow_mode="swarm",
        budgets={"max_spawned_agents": 1, "parallel_width": 1, "max_concurrent_delegated_work": 1},
        blueprint={"policy": {"allowed_tools": ["cowork_internal", "read_file"], "allow_exec": False}},
    )
    detail = service.record_full_observation_detail(
        session,
        subject_id="tool_private",
        subject_type="tool_observation",
        summary="Private tool result",
        content="secret",
        sensitivity="private",
        permitted_agent_ids=["other"],
        save=False,
    )

    created = service.request_agent_delegation(
        session,
        parent_agent_id="lead",
        task_goal="Use permitted context only.",
        input_references=[{"type": "observation_detail", "ref": detail.id}],
        tools=["cowork_internal", "read_file", "exec"],
    )

    assert not isinstance(created, str)
    brief = created["brief"]
    sub_agent = created["sub_agent"]
    assert brief.allowed_tools == ["cowork_internal", "read_file"]
    assert brief.input_references == []
    assert brief.redacted_reference_count == 1
    assert sub_agent.tools == ["cowork_internal", "read_file"]

    denied = service.request_agent_delegation(
        session,
        parent_agent_id="lead",
        task_goal="Try a second concurrent delegation.",
        tools=["cowork_internal"],
        save=False,
    )

    assert isinstance(denied, str)
    assert "delegation denied" in denied
    assert any(
        "spawned_agent_budget_exhausted" in item.denied_reasons for item in session.delegation_guardrails.values()
    )


def test_sub_agent_result_retires_agent_and_preserves_history(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session(
        "Complete delegated work",
        "Delegated result",
        [{"id": "lead", "name": "Lead", "role": "Coordinator", "goal": "Coordinate"}],
        [],
        budgets={"max_spawned_agents": 1, "parallel_width": 1},
    )
    created = service.request_agent_delegation(
        session,
        parent_agent_id="lead",
        task_goal="Answer one bounded question.",
        tools=["cowork_internal"],
    )
    assert not isinstance(created, str)
    sub_agent = created["sub_agent"]

    result = service.complete_sub_agent(
        session,
        sub_agent.id,
        answer="The answer is available.",
        evidence=[{"summary": "Checked the brief"}],
        sources=["brief"],
        uncertainty="Low",
        artifacts=["artifact://answer"],
    )

    assert not isinstance(result, str)
    delegated = session.delegated_tasks[sub_agent.delegated_task_id]
    assert delegated.status == "completed"
    assert delegated.result_id == result.id
    assert session.agents[sub_agent.id].lifecycle_status == "retired"
    assert session.agents[sub_agent.id].status == "retired"
    assert sub_agent.id not in [agent.id for agent in service.select_active_agents(session, limit=10)]
    assert result.answer == "The answer is available."
    assert any(event.type == "delegation.result.returned" for event in session.events)
    assert any(event.type == "agent.retired" for event in session.events)


def test_default_team_fallback_and_ready_task_dependencies(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session(
        "Launch a small workshop",
        "Workshop",
        [],
        [
            {
                "id": "first",
                "title": "First",
                "description": "First task",
                "assigned_agent_id": "coordinator",
            },
            {
                "id": "second",
                "title": "Second",
                "description": "Depends on first",
                "assigned_agent_id": "analyst",
                "dependencies": ["first"],
            },
        ],
    )

    assert {"coordinator", "researcher", "analyst"} <= set(session.agents)
    assert [task.id for task in service.ready_tasks_for(session, "analyst")] == []

    service.complete_task(session, "first", "done")

    assert [task.id for task in service.ready_tasks_for(session, "analyst")] == ["second"]


def test_unassigned_tasks_can_be_claimed_from_shared_pool(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session(
        "Share work",
        "Shared",
        [
            {"id": "lead", "name": "Lead", "role": "Lead", "goal": "Coordinate", "responsibilities": []},
            {"id": "worker", "name": "Worker", "role": "Worker", "goal": "Execute", "responsibilities": []},
        ],
        [{"id": "1", "title": "Open task", "description": "Can be claimed"}],
    )

    assert session.tasks["1"].assigned_agent_id is None
    assert [task.id for task in service.claimable_tasks_for(session, "worker")] == ["1"]

    claimed = service.claim_task(session, "worker", "1")

    assert not isinstance(claimed, str)
    assert claimed.assigned_agent_id == "worker"
    assert session.agents["worker"].status == "waiting"
    assert any(event.type == "task.claimed" for event in session.events)


def test_assign_task_moves_shared_task_to_specific_agent(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session(
        "Assign work", "Assign", [], [{"id": "open", "title": "Open", "description": "Open"}]
    )

    result = service.assign_task(session, "open", "analyst")

    assert "assigned to Analyst" in result
    assert session.tasks["open"].assigned_agent_id == "analyst"
    assert session.agents["analyst"].status == "waiting"
    assert session.events[-1].type == "task.assigned"


def test_message_routing_updates_thread_membership_and_inbox(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session("Compare options", "Options", [], [])
    first, second = list(session.agents)[:2]
    service.mark_messages_read(session, second)
    thread = service.create_thread(session, "Review", [first])

    message = service.send_message(session, first, [second], "Please review", thread_id=thread.id)

    assert second in session.threads[thread.id].participant_ids
    assert session.threads[thread.id].last_message_at == message.created_at
    assert session.agents[second].inbox == [message.id]


def test_unanswered_read_mailbox_request_keeps_agent_ready(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session("Keep ready", "Ready", [], [])
    sender, recipient = list(session.agents)[:2]
    record = CoworkMailboxRecord(
        id="env_waiting",
        sender_id=sender,
        recipient_ids=[recipient],
        content="Need a reply",
        status="read",
        requires_reply=True,
        priority=70,
    )
    service.add_mailbox_record(session, record)
    service.mark_messages_read(session, recipient)

    active = service.select_active_agents(session, limit=1)

    assert [agent.id for agent in active] == [recipient]


def test_assess_session_reports_blockers_and_readiness(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session("Assess blockers", "Assess", [], [])
    sender, recipient = list(session.agents)[:2]
    service.add_mailbox_record(
        session,
        CoworkMailboxRecord(
            id="env_blocker",
            sender_id=sender,
            recipient_ids=[recipient],
            content="Need verification",
            status="read",
            requires_reply=True,
            request_type="verify",
            blocking_task_id="1",
            priority=80,
        ),
    )

    decision = service.assess_session(session)

    assert decision["next_action"] == "resolve_blockers"
    assert decision["blocked"][0]["request_type"] == "verify"
    assert decision["readiness"][0]["agent_id"] == recipient


def test_mailbox_records_are_trimmed_to_bounded_size(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session("Trim mailbox", "Trim", [], [])
    agent_id = next(iter(session.agents))

    for index in range(305):
        service.add_mailbox_record(
            session,
            CoworkMailboxRecord(
                id=f"env_{index}",
                sender_id="user",
                recipient_ids=[agent_id],
                content=f"Message {index}",
                status="replied" if index < 10 else "delivered",
            ),
            save=False,
        )

    service.trim_mailbox_records(session)

    assert len(session.mailbox) == 300
    assert "env_0" not in session.mailbox
    assert any(event.type == "mailbox.trimmed" for event in session.events)


def test_failed_and_skipped_tasks_use_consistent_agent_status_and_events(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session("Classify work", "Classify", [], [])
    task_id = next(iter(session.tasks))
    agent_id = session.tasks[task_id].assigned_agent_id

    service.complete_task(session, task_id, "blocked by missing input", status="failed")

    assert session.tasks[task_id].status == "failed"
    assert session.tasks[task_id].error == "blocked by missing input"
    assert session.agents[agent_id].status == "failed"
    assert session.events[-1].type == "task.failed"

    skipped = service.add_task(session, "Optional", "Optional check", agent_id)
    service.complete_task(session, skipped.id, "not needed", status="skipped")

    assert skipped.status == "skipped"
    assert session.agents[agent_id].status == "idle"
    assert session.events[-1].type == "task.skipped"


def test_failed_agent_run_persists_task_failure(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session("Handle exception", "Exception", [], [])
    task_id = next(iter(session.tasks))
    agent_id = session.tasks[task_id].assigned_agent_id
    session.agents[agent_id].current_task_id = task_id
    session.agents[agent_id].current_task_title = session.tasks[task_id].title

    service.fail_agent_run(session, agent_id, "runner exploded")

    assert session.agents[agent_id].status == "failed"
    assert session.agents[agent_id].current_task_id is None
    assert session.tasks[task_id].status == "failed"
    assert session.tasks[task_id].error == "runner exploded"
    assert [event.type for event in session.events[-2:]] == ["task.failed", "agent.failed"]


def test_update_agent_after_run_creates_visible_user_message(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session("Share progress", "Progress", [], [])
    agent_id = next(iter(session.agents))
    service.mark_messages_read(session, agent_id)

    service.update_agent_after_run(session, agent_id, "I finished the first check.", status="idle")

    visible = [message for message in session.messages.values() if message.sender_id == agent_id]
    assert visible
    assert visible[-1].recipient_ids == ["user"]
    assert visible[-1].content == "I finished the first check."


def test_delete_session_removes_persisted_session(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session("Temporary", "Temporary", [], [])

    assert service.delete_session(session.id) is True
    assert service.get_session(session.id) is None
    assert CoworkService(temp_workspace).get_session(session.id) is None
    assert service.delete_session(session.id) is False


def test_cowork_events_notify_listeners(temp_workspace):
    service = CoworkService(temp_workspace)
    session = service.create_session("Notify progress", "Notify", [], [])
    received = []

    service.add_listener(lambda changed, event: received.append((changed.id, event.type)))
    service.add_event(session, "agent.started", "Coordinator started", actor_id="coordinator")

    assert received[-1] == (session.id, "agent.started")
