"""Stub-mode tests — exercise the agent without an OPENAI_API_KEY.

The agent must emit a canned reply with `token` + `final` events instead
of calling out to OpenAI, mirroring the pattern used by ai_insights.py.
"""
from __future__ import annotations

import pytest

from apps.core.assistant.agent import STUB_REPLY, run_turn_streaming
from apps.core.assistant.models import Conversation


@pytest.mark.django_db
def test_stub_mode_emits_canned_reply(learner_user, settings):
    settings.OPENAI_API_KEY = ""
    conv = Conversation.objects.create(user=learner_user, title="")
    events = list(run_turn_streaming(conv, learner_user, "Hello, what can you do?"))
    types = [e["type"] for e in events]
    assert "token" in types
    assert types[-1] == "final"
    full_text = "".join(e["payload"]["text"] for e in events if e["type"] == "token")
    assert full_text == STUB_REPLY
    assert events[-1]["payload"].get("stub") is True


@pytest.mark.django_db
def test_run_turn_does_not_call_openai_without_key(learner_user, settings, monkeypatch):
    """Even when ChatOpenAI is importable, an empty API key must short-circuit
    before any network/SDK call."""
    settings.OPENAI_API_KEY = ""

    called = {"flag": False}

    class _Boom:
        def __init__(self, *a, **kw):
            called["flag"] = True

    monkeypatch.setattr("langchain_openai.ChatOpenAI", _Boom, raising=False)

    conv = Conversation.objects.create(user=learner_user, title="")
    list(run_turn_streaming(conv, learner_user, "ignore me"))
    assert called["flag"] is False
