# -*- coding: utf-8 -*-
"""CN InfoHelpCommands 测试（Phase 8 Tier 2）

借鉴 zhikuncode InfoHelpCommands.java：
- /stats — 会话统计（消息数/工具调用数/文件修改数/持续时间）
- /advisor — AI 顾问模式（不直接改代码，只给建议）
- /btw — 顺便提问（不中断当前任务）
- /version — 版本信息（Python/abyss/OS）
"""
import platform
import sys
from unittest.mock import MagicMock

import pytest

from abyss.commands.info import (
    handle_stats,
    handle_advisor,
    handle_btw,
    handle_version,
    count_messages_by_role,
    count_tool_calls,
    format_duration,
)


def _make_messages_with_tool_calls() -> list:
    """构造含 tool_calls 的消息"""
    return [
        {"role": "system", "content": "sys"},
        {"role": "user", "content": "edit demo.py"},
        {
            "role": "assistant",
            "content": None,
            "tool_calls": [
                {"id": "1", "type": "function", "function": {"name": "file_edit", "arguments": "{}"}},
                {"id": "2", "type": "function", "function": {"name": "file_read", "arguments": "{}"}},
            ],
        },
        {"role": "tool", "content": "result 1", "tool_call_id": "1"},
        {"role": "tool", "content": "result 2", "tool_call_id": "2"},
        {"role": "assistant", "content": "done"},
    ]


class TestCountMessagesByRole:
    """count_messages_by_role 测试"""

    def test_counts_each_role(self):
        messages = _make_messages_with_tool_calls()
        counts = count_messages_by_role(messages)
        assert counts["system"] == 1
        assert counts["user"] == 1
        assert counts["assistant"] == 2
        assert counts["tool"] == 2

    def test_empty_messages(self):
        assert count_messages_by_role([]) == {}

    def test_unknown_role_counted(self):
        messages = [{"role": "developer", "content": "x"}]
        counts = count_messages_by_role(messages)
        assert counts["developer"] == 1


class TestCountToolCalls:
    """count_tool_calls 测试"""

    def test_counts_tool_calls_in_assistant_messages(self):
        messages = _make_messages_with_tool_calls()
        assert count_tool_calls(messages) == 2

    def test_zero_when_no_tool_calls(self):
        messages = [{"role": "user", "content": "hi"}]
        assert count_tool_calls(messages) == 0

    def test_empty_messages(self):
        assert count_tool_calls([]) == 0


class TestFormatDuration:
    """format_duration 测试"""

    def test_seconds(self):
        assert format_duration(45) == "45s"

    def test_minutes(self):
        assert format_duration(120) == "2m 0s"

    def test_hours(self):
        assert format_duration(3661) == "1h 1m 1s"

    def test_zero(self):
        assert format_duration(0) == "0s"


class TestHandleStats:
    """handle_stats 测试"""

    def test_counts_messages_correctly(self):
        session = MagicMock()
        session.messages = _make_messages_with_tool_calls()
        result = handle_stats(session)
        assert "user" in result.lower() or "用户" in result
        assert "assistant" in result.lower() or "助手" in result or "AI" in result
        assert "tool" in result.lower() or "工具" in result

    def test_counts_tool_calls(self):
        session = MagicMock()
        session.messages = _make_messages_with_tool_calls()
        result = handle_stats(session)
        assert "tool_call" in result.lower() or "工具调用" in result or "2" in result

    def test_shows_session_duration(self):
        session = MagicMock()
        session.messages = _make_messages_with_tool_calls()
        session.started_at = None
        result = handle_stats(session)
        # started_at None 时优雅降级
        assert isinstance(result, str)

    def test_empty_session_handled(self):
        session = MagicMock()
        session.messages = []
        result = handle_stats(session)
        assert isinstance(result, str)


class TestHandleAdvisor:
    """handle_advisor 测试"""

    def test_injects_advisory_prompt(self):
        session = MagicMock()
        result = handle_advisor(session, "how to improve my code")
        assert result == "injected"
        session.add_user.assert_called_once()
        args = session.add_user.call_args[0]
        assert "顾问" in args[0] or "advisor" in args[0].lower()
        assert "how to improve my code" in args[0]

    def test_no_target_returns_error(self):
        session = MagicMock()
        result = handle_advisor(session, "")
        assert result != "injected"
        assert "用法" in result or "usage" in result.lower()
        session.add_user.assert_not_called()


class TestHandleBtw:
    """handle_btw 测试"""

    def test_injects_inline_question(self):
        session = MagicMock()
        result = handle_btw(session, "what does async mean")
        assert result == "injected"
        session.add_user.assert_called_once()
        args = session.add_user.call_args[0]
        assert "顺便" in args[0] or "btw" in args[0].lower() or "interrupt" in args[0].lower()
        assert "what does async mean" in args[0]

    def test_no_target_returns_error(self):
        session = MagicMock()
        result = handle_btw(session, "")
        assert result != "injected"
        session.add_user.assert_not_called()


class TestHandleVersion:
    """handle_version 测试"""

    def test_shows_python_version(self):
        result = handle_version()
        assert "Python" in result
        assert platform.python_version() in result or "3." in result

    def test_shows_abyss_version(self):
        result = handle_version()
        # abyss version 来自 __init__.py
        assert "abyss" in result.lower() or "Abyss" in result

    def test_shows_os_info(self):
        result = handle_version()
        assert platform.system() in result or "Windows" in result or "Linux" in result or "Darwin" in result

    def test_returns_string(self):
        result = handle_version()
        assert isinstance(result, str)
        assert len(result) > 0
