from datetime import datetime
from types import SimpleNamespace

from src.chat.message_receive.message import SessionMessage
from src.common.data_models.mai_message_data_model import MessageInfo, UserInfo
from src.common.data_models.message_component_data_model import AtComponent, MessageSequence, ReplyComponent, TextComponent
from src.config.config import global_config
from src.maisaka.builtin_tool.context import BuiltinToolRuntimeContext


def _build_sent_message() -> SessionMessage:
    message = SessionMessage(
        message_id="real-message-id",
        timestamp=datetime(2026, 4, 5, 12, 0, 0),
        platform="qq",
    )
    message.message_info = MessageInfo(
        user_info=UserInfo(
            user_id="bot-qq",
            user_nickname="MaiSaka",
            user_cardname=None,
        ),
        group_info=None,
        additional_config={},
    )
    message.raw_message = MessageSequence(
        [
            ReplyComponent(target_message_id="m123"),
            TextComponent(text="你好"),
        ]
    )
    message.session_id = "test-session"
    message.initialized = True
    return message


def test_append_sent_message_to_chat_history_keeps_message_id() -> None:
    runtime = SimpleNamespace(_chat_history=[])
    engine = SimpleNamespace(_get_runtime_manager=lambda: None)
    tool_ctx = BuiltinToolRuntimeContext(engine=engine, runtime=runtime)

    tool_ctx.append_sent_message_to_chat_history(_build_sent_message())

    assert len(runtime._chat_history) == 1
    history_message = runtime._chat_history[0]
    assert history_message.message_id == "real-message-id"
    assert "[msg_id]real-message-id\n" in history_message.raw_message.components[0].text
    assert "[msg_id:real-message-id]" in history_message.visible_text


def test_post_process_reply_message_sequences_converts_at_marker_before_bracket_cleanup(monkeypatch) -> None:
    monkeypatch.setattr(global_config.chat, "enable_at", True)
    monkeypatch.setattr(
        "src.maisaka.builtin_tool.context.process_llm_response",
        lambda text: [text.strip()] if text.strip() else [],
    )
    target_message = SimpleNamespace(
        message_info=SimpleNamespace(
            user_info=SimpleNamespace(
                user_id="target-user",
                user_nickname="目标昵称",
                user_cardname="群名片",
            )
        )
    )
    runtime = SimpleNamespace(_source_messages_by_id={"12160142": target_message})
    engine = SimpleNamespace(_get_runtime_manager=lambda: None)
    tool_ctx = BuiltinToolRuntimeContext(engine=engine, runtime=runtime)

    sequences = tool_ctx.post_process_reply_message_sequences("at[12160142] 就这个群")

    assert len(sequences) == 1
    components = sequences[0].components
    assert isinstance(components[0], AtComponent)
    assert components[0].target_user_id == "target-user"
    assert components[0].target_user_nickname == "目标昵称"
    assert components[0].target_user_cardname == "群名片"
    assert isinstance(components[1], TextComponent)
    assert components[1].text == " 就这个群"


def test_post_process_reply_message_sequences_ignores_at_marker_when_disabled(monkeypatch) -> None:
    monkeypatch.setattr(global_config.chat, "enable_at", False)
    monkeypatch.setattr(
        "src.maisaka.builtin_tool.context.process_llm_response",
        lambda text: [text.strip()] if text.strip() else [],
    )
    runtime = SimpleNamespace(_source_messages_by_id={})
    engine = SimpleNamespace(_get_runtime_manager=lambda: None)
    tool_ctx = BuiltinToolRuntimeContext(engine=engine, runtime=runtime)

    sequences = tool_ctx.post_process_reply_message_sequences("at[12160142] 就这个群")

    assert len(sequences) == 1
    components = sequences[0].components
    assert len(components) == 1
    assert isinstance(components[0], TextComponent)
    assert components[0].text == "at[12160142] 就这个群"
