"""Tests for in-memory state backend (Redis tested in integration)."""

import asyncio
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).parent.parent))
from tests.conftest import _run
from app.models import EventType, RunEvent, RunRecord, RunStatus


def _make_run(run_id: str = "gr_test_001") -> RunRecord:
    return RunRecord(
        run_id=run_id,
        graph="release_check",
        status=RunStatus.QUEUED,
        agent_id="sofiia",
        workspace_id="daarion",
        user_id="u_001",
    )


class TestMemoryBackend:
    def test_save_and_get_run(self):
        from app.state_backend import MemoryStateBackend
        backend = MemoryStateBackend()
        run = _make_run("gr_001")
        _run(backend.save_run(run))
        fetched = _run(backend.get_run("gr_001"))
        assert fetched is not None
        assert fetched.run_id == "gr_001"
        assert fetched.status == RunStatus.QUEUED

    def test_get_missing_run_returns_none(self):
        from app.state_backend import MemoryStateBackend
        backend = MemoryStateBackend()
        assert _run(backend.get_run("does_not_exist")) is None

    def test_append_and_get_events(self):
        from app.state_backend import MemoryStateBackend
        backend = MemoryStateBackend()
        run = _make_run("gr_002")
        _run(backend.save_run(run))

        ev1 = RunEvent(ts="2026-01-01T00:00:00Z", type=EventType.NODE_START, node="start_job")
        ev2 = RunEvent(ts="2026-01-01T00:00:01Z", type=EventType.TOOL_CALL, tool="job_orchestrator_tool",
                       details={"hash": "abc123", "size": 200})
        _run(backend.append_event("gr_002", ev1))
        _run(backend.append_event("gr_002", ev2))

        events = _run(backend.get_events("gr_002"))
        assert len(events) == 2
        assert events[0].type == EventType.NODE_START
        assert events[1].tool == "job_orchestrator_tool"
        # Events should NOT contain payload content
        assert "size" in events[1].details

    def test_cancel_queued_run(self):
        from app.state_backend import MemoryStateBackend
        backend = MemoryStateBackend()
        run = _make_run("gr_003")
        _run(backend.save_run(run))

        ok = _run(backend.cancel_run("gr_003"))
        assert ok is True
        fetched = _run(backend.get_run("gr_003"))
        assert fetched.status == RunStatus.CANCELLED

    def test_cancel_completed_run_returns_false(self):
        from app.state_backend import MemoryStateBackend
        backend = MemoryStateBackend()
        run = _make_run("gr_004")
        run.status = RunStatus.SUCCEEDED
        _run(backend.save_run(run))

        ok = _run(backend.cancel_run("gr_004"))
        assert ok is False

    def test_update_run_status(self):
        from app.state_backend import MemoryStateBackend
        backend = MemoryStateBackend()
        run = _make_run("gr_005")
        _run(backend.save_run(run))

        run.status = RunStatus.RUNNING
        run.started_at = "2026-01-01T00:00:00Z"
        _run(backend.save_run(run))

        fetched = _run(backend.get_run("gr_005"))
        assert fetched.status == RunStatus.RUNNING
        assert fetched.started_at == "2026-01-01T00:00:00Z"
