"""End-to-end scenario test for file operations.

This test simulates a realistic scenario where an agent:
1. Reads a file
2. Explains its content
3. Creates a new file with analysis results

This is a meaningful e2e test that demonstrates the agent's ability to
orchestrate multiple tool calls in sequence.
"""

from __future__ import annotations

import os
import tempfile
from pathlib import Path

import pytest

from agentlite import Agent, tool


# =============================================================================
# File Operation Tools
# =============================================================================


@tool()
async def read_file(file_path: str) -> str:
    """Read the content of a file.

    Args:
        file_path: Path to the file to read.

    Returns:
        The content of the file as a string.

    Raises:
        FileNotFoundError: If the file does not exist.
    """
    with open(file_path) as f:
        return f.read()


@tool()
async def write_file(file_path: str, content: str) -> str:
    """Write content to a file, creating it if it doesn't exist.

    Args:
        file_path: Path to the file to write.
        content: Content to write to the file.

    Returns:
        Success message confirming the file was written.
    """
    # Create parent directories if they don't exist
    Path(file_path).parent.mkdir(parents=True, exist_ok=True)

    with open(file_path, "w") as f:
        f.write(content)

    return f"File successfully written to {file_path}"


@tool()
async def list_files(directory: str) -> str:
    """List all files in a directory.

    Args:
        directory: Path to the directory to list.

    Returns:
        A newline-separated list of file names in the directory.
    """
    files = os.listdir(directory)
    return "\n".join(files)


# =============================================================================
# E2E Test
# =============================================================================


@pytest.mark.scenario
class TestFileOperationsScenario:
    """End-to-end test for file read/write operations."""

    @pytest.mark.asyncio
    async def test_read_explain_and_write(self, mock_provider):
        """Test a complete workflow: read file -> explain -> write results."""
        # Setup: Create a temporary file with content
        with tempfile.TemporaryDirectory() as tmpdir:
            # Create a source file to read
            source_file = os.path.join(tmpdir, "source.txt")
            source_content = """Project Overview
================

This is a sample project document for testing.

Features:
- Feature A: Does something useful
- Feature B: Does something else
- Feature C: The most important feature

Conclusion: This project demonstrates file operations.
"""
            with open(source_file, "w") as f:
                f.write(source_content)

            # Configure mock provider responses
            # The agent should:
            # 1. Read the file
            # 2. Summarize it
            # 3. Write the summary to a new file
            mock_provider.add_text_response(
                f"I'll read the file at {source_file} and analyze it for you."
            )

            # Create agent with file tools
            tools = [read_file, write_file, list_files]
            agent = Agent(
                provider=mock_provider,
                tools=tools,
                system_prompt="You are a helpful file analysis assistant.",
            )

            # Step 1: Agent reads and analyzes the file
            mock_provider.clear_responses()
            mock_provider.add_tool_call(
                "read_file",
                {"file_path": source_file},
                source_content,
            )

            # Agent analyzes the content
            mock_provider.add_text_response(
                "I've read the file. It's a project overview document with 3 features. "
                "Let me create a summary file."
            )

            # Step 2: Agent writes summary to a new file
            summary_file = os.path.join(tmpdir, "summary.txt")
            expected_summary = """Project Summary
================

This is a sample project with 3 main features:
- Feature A, - Feature B, - Feature C

The most important feature is Feature C.
"""

            mock_provider.clear_responses()
            mock_provider.add_tool_call(
                "write_file",
                {
                    "file_path": summary_file,
                    "content": expected_summary,
                },
                f"File successfully written to {summary_file}",
            )
            mock_provider.add_text_response(f"I've created a summary at {summary_file}")

            # Execute the agent
            response = await agent.run(
                f"Please read {source_file}, analyze it, and create a summary file at {summary_file}"
            )

            # Verify the interaction
            assert "summary" in response.lower()

            # Verify the provider was called correctly
            assert len(mock_provider.calls) >= 1

    @pytest.mark.asyncio
    async def test_list_files_scenario(self, mock_provider):
        """Test listing files in a directory."""
        with tempfile.TemporaryDirectory() as tmpdir:
            # Create some test files
            for i in range(3):
                with open(os.path.join(tmpdir, f"file{i}.txt"), "w") as f:
                    f.write(f"Content {i}")

            # Configure agent to list files
            mock_provider.add_tool_call(
                "list_files",
                {"directory": tmpdir},
                "file0.txt\nfile1.txt\nfile2.txt",
            )
            mock_provider.add_text_response(
                f"I found 3 files in {tmpdir}: file0.txt, file1.txt, file2.txt"
            )

            agent = Agent(
                provider=mock_provider,
                tools=[list_files],
                system_prompt="You are a file system assistant.",
            )

            response = await agent.run(f"List all files in {tmpdir}")

            assert "3 files" in response

    @pytest.mark.asyncio
    async def test_multi_step_file_workflow(self, mock_provider):
        """Test a complex multi-step file workflow.

        Scenario:
        1. List files in directory
        2. Read each file
        3. Create a combined report
        """
        with tempfile.TemporaryDirectory() as tmpdir:
            # Create test files
            files_content = {
                "report1.txt": "Sales increased by 20%",
                "report2.txt": "Customer satisfaction at 85%",
                "report3.txt": "Bug fixes: 15 resolved",
            }

            for name, content in files_content.items():
                with open(os.path.join(tmpdir, name), "w") as f:
                    f.write(content)

            # Configure agent responses for multi-step workflow
            tools = [read_file, write_file, list_files]

            # Step 1: List files
            mock_provider.add_tool_call(
                "list_files",
                {"directory": tmpdir},
                "report1.txt\nreport2.txt\nreport3.txt",
            )

            # Step 2: Read all files
            mock_provider.add_tool_call(
                "read_file",
                {"file_path": os.path.join(tmpdir, "report1.txt")},
                "Sales increased by 20%",
            )
            mock_provider.add_tool_call(
                "read_file",
                {"file_path": os.path.join(tmpdir, "report2.txt")},
                "Customer satisfaction at 85%",
            )
            mock_provider.add_tool_call(
                "read_file",
                {"file_path": os.path.join(tmpdir, "report3.txt")},
                "Bug fixes: 15 resolved",
            )

            # Step 3: Write combined report
            combined_report = """Combined Report
================

1. Sales: Increased by 20%
2. Customer Satisfaction: 85%
3. Development: 15 bugs resolved
"""
            mock_provider.add_tool_call(
                "write_file",
                {
                    "file_path": os.path.join(tmpdir, "combined_report.txt"),
                    "content": combined_report,
                },
                f"File successfully written to {os.path.join(tmpdir, 'combined_report.txt')}",
            )

            mock_provider.add_text_response(
                "I've created a combined report summarizing all three reports."
            )

            agent = Agent(
                provider=mock_provider,
                tools=tools,
                system_prompt="You are a report analyst assistant.",
            )

            response = await agent.run(
                f"List all files in {tmpdir}, read them all, and create a combined report at combined_report.txt"
            )

            assert "combined report" in response.lower()


# =============================================================================
# Additional Tools for Extended Scenarios
# =============================================================================


@tool()
async def count_words(file_path: str) -> str:
    """Count the number of words in a file.

    Args:
        file_path: Path to the file to analyze.

    Returns:
        The word count as a string.
    """
    with open(file_path) as f:
        content = f.read()
        word_count = len(content.split())
        return f"Word count: {word_count}"


@tool()
async def append_to_file(file_path: str, content: str) -> str:
    """Append content to an existing file.

    Args:
        file_path: Path to the file to append to.
        content: Content to append.

    Returns:
        Success message.
    """
    with open(file_path, "a") as f:
        f.write("\n" + content)
    return f"Content appended to {file_path}"


@pytest.mark.scenario
class TestExtendedFileOperations:
    """Extended scenarios with more file operations."""

    @pytest.mark.asyncio
    async def test_read_count_and_append(self, mock_provider):
        """Test reading a file, counting words, and appending a note."""
        with tempfile.TemporaryDirectory() as tmpdir:
            source_file = os.path.join(tmpdir, "document.txt")
            with open(source_file, "w") as f:
                f.write("This is a test document with several words in it.")

            tools = [read_file, write_file, count_words, append_to_file]

            # Step 1: Read file
            mock_provider.add_tool_call(
                "read_file",
                {"file_path": source_file},
                "This is a test document with several words in it.",
            )

            # Step 2: Count words
            mock_provider.add_tool_call(
                "count_words",
                {"file_path": source_file},
                "Word count: 10",
            )

            # Step 3: Append analysis
            mock_provider.add_tool_call(
                "append_to_file",
                {
                    "file_path": source_file,
                    "content": "\n\n[Analysis] This document contains 10 words.",
                },
                f"Content appended to {source_file}",
            )

            mock_provider.add_text_response(
                "I've analyzed the document and appended the word count analysis."
            )

            agent = Agent(
                provider=mock_provider,
                tools=tools,
                system_prompt="You are a document analysis assistant.",
            )

            response = await agent.run(
                f"Read {source_file}, count its words, and append the word count as an analysis note"
            )

            assert "analyzed" in response.lower()
