"""Tests for Summarizer."""

import asyncio
import datetime
import tempfile
from pathlib import Path

from agentscope.message import Msg
from agentscope.tool import Toolkit
from test_utils import (
    get_dash_chat_model,
    get_formatter,
    get_token_counter,
)
from reme.core.utils import get_logger
from reme.memory.file_based.components import Summarizer
from reme.memory.file_based.tools import FileIO


logger = get_logger()


# ANSI 颜色码
class Colors:
    """ANSI color codes for terminal output."""

    GREEN = "\033[92m"
    RED = "\033[91m"
    YELLOW = "\033[93m"
    BLUE = "\033[94m"
    CYAN = "\033[96m"
    BOLD = "\033[1m"
    RESET = "\033[0m"


def print_pass(test_name: str):
    """打印测试通过信息"""
    print(f"{Colors.GREEN}{Colors.BOLD}✓ {test_name} PASSED{Colors.RESET}")


def print_fail(test_name: str, error: str):
    """打印测试失败信息"""
    print(f"{Colors.RED}{Colors.BOLD}✗ {test_name} FAILED: {error}{Colors.RESET}")


def print_error(test_name: str, error: str):
    """打印测试错误信息"""
    print(f"{Colors.YELLOW}{Colors.BOLD}⚠ {test_name} ERROR: {error}{Colors.RESET}")


def print_test_header(test_name: str):
    """打印测试标题"""
    print(f"\n{Colors.CYAN}{'=' * 60}{Colors.RESET}")
    print(f"{Colors.BLUE}{Colors.BOLD}Running: {test_name}{Colors.RESET}")
    print(f"{Colors.CYAN}{'=' * 60}{Colors.RESET}")


def create_user_msg(content: str) -> Msg:
    """Create a user message."""
    return Msg(name="user", role="user", content=content)


def create_assistant_msg(content: str) -> Msg:
    """Create an assistant message."""
    return Msg(name="assistant", role="assistant", content=content)


def create_tool_use_msg(tool_name: str, tool_input: dict) -> Msg:
    """Create a message with tool_use content block."""
    return Msg(
        name="assistant",
        role="assistant",
        content=[
            {
                "type": "tool_use",
                "id": "call_123",
                "name": tool_name,
                "input": tool_input,
            },
        ],
    )


def create_tool_result_msg(tool_name: str, output: str) -> Msg:
    """Create a message with tool_result content block."""
    return Msg(
        name="tool",
        role="user",
        content=[
            {
                "type": "tool_result",
                "id": "call_123",
                "name": tool_name,
                "output": output,
            },
        ],
    )


def create_toolkit(working_dir: str) -> Toolkit:
    """Create a default Toolkit with FileIO tools for testing."""
    toolkit = Toolkit()
    file_io = FileIO(working_dir=working_dir)
    toolkit.register_tool_function(file_io.read_file)
    toolkit.register_tool_function(file_io.write_file)
    toolkit.register_tool_function(file_io.edit_file)
    return toolkit


def create_summarizer(working_dir: str = None, memory_dir: str = "memory"):
    """Create a Summarizer instance for testing."""
    if working_dir is None:
        working_dir = tempfile.mkdtemp()

    # 确保 memory_dir 存在
    memory_path = Path(working_dir) / memory_dir
    memory_path.mkdir(parents=True, exist_ok=True)

    return (
        Summarizer(
            working_dir=working_dir,
            memory_dir=memory_dir,
            memory_compact_threshold=4000,
            as_token_counter=get_token_counter(),
            toolkit=create_toolkit(working_dir),
            as_llm=get_dash_chat_model(),
            as_llm_formatter=get_formatter(),
        ),
        working_dir,
    )


def test_empty_messages():
    """Test that empty messages return empty string."""
    summarizer, _ = create_summarizer()
    result = asyncio.run(summarizer.call(messages=[]))
    assert result == "", f"Expected empty string, got: {result}"
    print_pass("test_empty_messages")


def test_short_conversation():
    """Test summarization of a short conversation."""
    summarizer, working_dir = create_summarizer()
    messages = [
        create_user_msg("Hello, I need help with Python."),
        create_assistant_msg("Sure, I'd be happy to help. What do you need?"),
        create_user_msg("How do I read a file?"),
        create_assistant_msg("You can use open() function: with open('file.txt', 'r') as f: content = f.read()"),
    ]

    logger.info(f"Input messages count: {len(messages)}")
    logger.info(f"Working directory: {working_dir}")

    result = asyncio.run(summarizer.call(messages=messages))

    logger.info(f"Result type: {type(result)}")
    logger.info(f"Result: {result}")

    assert result, "Result should not be empty"
    assert isinstance(result, str), f"Result should be string, got: {type(result)}"
    print_pass("test_short_conversation")


def test_conversation_with_tool_calls():
    """Test summarization of conversation with tool calls."""
    summarizer, working_dir = create_summarizer()
    messages = [
        create_user_msg("Help me debug this Python script."),
        create_assistant_msg("Let me check the script first."),
        create_tool_use_msg("read_file", {"path": "/app/main.py"}),
        create_tool_result_msg("read_file", "def process():\n    data = load_data()\n    return data"),
        create_assistant_msg("I found the issue! The script needs error handling."),
        create_user_msg("How should I fix it?"),
        create_assistant_msg("Add try-except block around the load_data() call."),
    ]

    logger.info(f"Working directory: {working_dir}")
    result = asyncio.run(summarizer.call(messages=messages))

    assert result, "Result should not be empty"
    assert isinstance(result, str), f"Result should be string, got: {type(result)}"
    print_pass("test_conversation_with_tool_calls")


def test_consecutive_summaries():
    """Test consecutive summaries in the same directory.

    This test verifies that:
    1. First summary creates the memory file
    2. Second summary reads and updates the existing file
    """
    # 使用固定的临时目录
    working_dir = tempfile.mkdtemp()
    memory_dir = "memory"
    memory_path = Path(working_dir) / memory_dir
    memory_path.mkdir(parents=True, exist_ok=True)

    logger.info(f"Working directory: {working_dir}")
    logger.info(f"Memory path: {memory_path}")

    # 创建 Summarizer 实例
    summarizer = Summarizer(
        working_dir=working_dir,
        memory_dir=memory_dir,
        memory_compact_threshold=4000,
        as_token_counter=get_token_counter(),
        toolkit=create_toolkit(working_dir),
        as_llm=get_dash_chat_model(),
        as_llm_formatter=get_formatter(),
    )

    # 第一轮对话
    messages_round1 = [
        create_user_msg("My name is Alice and I'm learning Python."),
        create_assistant_msg("Nice to meet you, Alice! Python is a great language to learn."),
        create_user_msg("I prefer using VS Code as my editor."),
        create_assistant_msg("VS Code is excellent for Python development with great extensions."),
    ]

    logger.info("=" * 40)
    logger.info("Round 1: First summary (creating new file)")
    logger.info("=" * 40)
    result1 = asyncio.run(summarizer.call(messages=messages_round1))
    logger.info(f"Round 1 Result:\n{result1}")

    # 检查文件是否被创建
    today = datetime.datetime.now().strftime("%Y-%m-%d")
    expected_file = memory_path / f"{today}.md"
    logger.info(f"Expected file: {expected_file}")

    # 列出目录内容
    files_after_round1 = list(memory_path.iterdir())
    logger.info(f"Files after round 1: {files_after_round1}")

    assert expected_file.exists(), f"Memory file should be created at {expected_file}"

    # 读取第一轮写入的内容
    content_after_round1 = expected_file.read_text()
    logger.info(f"Content after round 1:\n{content_after_round1}")

    # 第二轮对话
    messages_round2 = [
        create_user_msg("I also like using Docker for my projects."),
        create_assistant_msg("Docker is great for containerization and deployment."),
        create_user_msg("My favorite framework is FastAPI."),
        create_assistant_msg("FastAPI is excellent for building modern APIs with Python."),
    ]

    logger.info("=" * 40)
    logger.info("Round 2: Second summary (reading and updating existing file)")
    logger.info("=" * 40)
    result2 = asyncio.run(summarizer.call(messages=messages_round2))
    logger.info(f"Round 2 Result:\n{result2}")

    # 读取第二轮写入后的内容
    content_after_round2 = expected_file.read_text()
    logger.info(f"Content after round 2:\n{content_after_round2}")

    # 验证
    assert result1, "Round 1 result should not be empty"
    assert result2, "Round 2 result should not be empty"

    # 验证第二轮内容包含新信息（Docker 或 FastAPI）
    # 注意：具体内容取决于 LLM 的响应
    assert len(content_after_round2) > 0, "Content after round 2 should not be empty"

    logger.info("=" * 40)
    logger.info("Consecutive summaries test completed successfully!")
    logger.info("=" * 40)

    print_pass("test_consecutive_summaries")


def run_all_tests():
    """Run all tests."""
    tests = [
        test_consecutive_summaries,
        test_empty_messages,
        test_short_conversation,
        test_conversation_with_tool_calls,
    ]

    passed = 0
    failed = 0

    for test in tests:
        try:
            print_test_header(test.__name__)
            test()
            passed += 1
        except AssertionError as e:
            print_fail(test.__name__, str(e))
            failed += 1
        except Exception as e:
            import traceback

            print_error(test.__name__, str(e))
            traceback.print_exc()
            failed += 1

    # 打印最终统计结果
    print(f"\n{Colors.CYAN}{'=' * 60}{Colors.RESET}")
    print(f"{Colors.BOLD}Test Results Summary{Colors.RESET}")
    print(f"{Colors.CYAN}{'=' * 60}{Colors.RESET}")
    print(f"{Colors.GREEN}{Colors.BOLD}✓ Passed: {passed}{Colors.RESET}")
    if failed > 0:
        print(f"{Colors.RED}{Colors.BOLD}✗ Failed: {failed}{Colors.RESET}")
    else:
        print(f"{Colors.GREEN}✗ Failed: {failed}{Colors.RESET}")
    print(f"{Colors.CYAN}{'=' * 60}{Colors.RESET}")

    if failed == 0:
        print(f"\n{Colors.GREEN}{Colors.BOLD}🎉 All tests passed!{Colors.RESET}")
    else:
        print(f"\n{Colors.RED}{Colors.BOLD}💥 Some tests failed!{Colors.RESET}")


if __name__ == "__main__":
    run_all_tests()
