"""Platform IO legacy driver 回归测试。"""

from typing import Any, Dict, Optional

import pytest

from src.chat.utils import utils as chat_utils
from src.chat.message_receive import uni_message_sender
from src.platform_io.drivers.base import PlatformIODriver
from src.platform_io.drivers.legacy_driver import LegacyPlatformDriver
from src.platform_io.manager import PlatformIOManager
from src.platform_io.types import DeliveryReceipt, DeliveryStatus, DriverDescriptor, DriverKind, RouteBinding, RouteKey


class _PluginDriver(PlatformIODriver):
    """测试用插件发送驱动。"""

    def __init__(self, driver_id: str, platform: str) -> None:
        """初始化测试驱动。

        Args:
            driver_id: 驱动 ID。
            platform: 负责的平台名称。
        """
        super().__init__(
            DriverDescriptor(
                driver_id=driver_id,
                kind=DriverKind.PLUGIN,
                platform=platform,
                plugin_id="test.plugin",
            )
        )

    async def send_message(
        self,
        message: Any,
        route_key: RouteKey,
        metadata: Optional[Dict[str, Any]] = None,
    ) -> DeliveryReceipt:
        """返回一个固定成功回执。

        Args:
            message: 待发送消息。
            route_key: 当前路由键。
            metadata: 发送元数据。

        Returns:
            DeliveryReceipt: 固定成功回执。
        """
        del metadata
        return DeliveryReceipt(
            internal_message_id=str(message.message_id),
            route_key=route_key,
            status=DeliveryStatus.SENT,
            driver_id=self.driver_id,
            driver_kind=self.descriptor.kind,
        )


@pytest.mark.asyncio
async def test_platform_io_uses_legacy_driver_when_no_explicit_send_route(
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    """没有显式发送路由时，应由 Platform IO 回退到 legacy driver。"""
    manager = PlatformIOManager()
    monkeypatch.setattr(chat_utils, "get_all_bot_accounts", lambda: {"qq": "bot-qq"})

    try:
        await manager.ensure_send_pipeline_ready()

        fallback_drivers = manager.resolve_drivers(RouteKey(platform="qq"))
        assert [driver.driver_id for driver in fallback_drivers] == ["legacy.send.qq"]

        plugin_driver = _PluginDriver(driver_id="plugin.qq.sender", platform="qq")
        await manager.add_driver(plugin_driver)
        manager.bind_send_route(
            RouteBinding(
                route_key=RouteKey(platform="qq"),
                driver_id=plugin_driver.driver_id,
                driver_kind=plugin_driver.descriptor.kind,
            )
        )

        explicit_drivers = manager.resolve_drivers(RouteKey(platform="qq"))
        assert [driver.driver_id for driver in explicit_drivers] == ["plugin.qq.sender", "legacy.send.qq"]
    finally:
        await manager.stop()


@pytest.mark.asyncio
async def test_platform_io_broadcasts_to_plugin_and_legacy_driver(
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    """同一路由命中插件驱动与 legacy driver 时，应同时广播发送。"""

    manager = PlatformIOManager()
    legacy_calls: list[dict[str, Any]] = []
    monkeypatch.setattr(chat_utils, "get_all_bot_accounts", lambda: {"qq": "bot-qq"})

    async def _fake_send_prepared_message_to_platform(message: Any, show_log: bool = True) -> bool:
        """记录 legacy driver 调用。"""

        legacy_calls.append({"message": message, "show_log": show_log})
        return True

    monkeypatch.setattr(
        uni_message_sender,
        "send_prepared_message_to_platform",
        _fake_send_prepared_message_to_platform,
    )

    try:
        await manager.ensure_send_pipeline_ready()

        plugin_driver = _PluginDriver(driver_id="plugin.qq.sender", platform="qq")
        await manager.add_driver(plugin_driver)
        manager.bind_send_route(
            RouteBinding(
                route_key=RouteKey(platform="qq"),
                driver_id=plugin_driver.driver_id,
                driver_kind=plugin_driver.descriptor.kind,
            )
        )

        message = type("FakeMessage", (), {"message_id": "message-1"})()
        batch = await manager.send_message(
            message=message,
            route_key=RouteKey(platform="qq"),
            metadata={"show_log": False},
        )

        assert sorted(receipt.driver_id for receipt in batch.sent_receipts) == [
            "legacy.send.qq",
            "plugin.qq.sender",
        ]
        assert batch.failed_receipts == []
        assert len(legacy_calls) == 1
        assert legacy_calls[0]["message"] is message
        assert legacy_calls[0]["show_log"] is False
    finally:
        await manager.stop()


@pytest.mark.asyncio
async def test_legacy_platform_driver_uses_prepared_universal_sender(
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    """legacy driver 应复用已预处理消息的旧链发送函数。"""
    calls: list[dict[str, Any]] = []

    async def _fake_send_prepared_message_to_platform(message: Any, show_log: bool = True) -> bool:
        """记录 legacy driver 调用。"""
        calls.append({"message": message, "show_log": show_log})
        return True

    monkeypatch.setattr(
        uni_message_sender,
        "send_prepared_message_to_platform",
        _fake_send_prepared_message_to_platform,
    )

    driver = LegacyPlatformDriver(
        driver_id="legacy.send.qq",
        platform="qq",
        account_id="bot-qq",
    )
    message = type("FakeMessage", (), {"message_id": "message-1"})()
    receipt = await driver.send_message(
        message=message,
        route_key=RouteKey(platform="qq"),
        metadata={"show_log": False},
    )

    assert len(calls) == 1
    assert calls[0]["message"] is message
    assert calls[0]["show_log"] is False
    assert receipt.status == DeliveryStatus.SENT
    assert receipt.driver_id == "legacy.send.qq"
