"""
Prompt Builder Module

Constructs prompts for the LLM with:
- System prompts with tool definitions
- Task planning prompts
- Code generation prompts
- Error diagnosis prompts
- Context formatting
"""

from dataclasses import dataclass
from typing import Any, Optional

from ai_coder.core.context import ProjectContext


@dataclass
class ToolDefinition:
    """Definition of a tool available to the agent."""

    name: str
    description: str
    parameters: dict[str, Any]


# Tool definitions for the agent
TOOLS = [
    ToolDefinition(
        name="read_file",
        description="Read the contents of a file at the given path",
        parameters={
            "type": "object",
            "properties": {
                "path": {
                    "type": "string",
                    "description": "Relative path to the file to read"
                }
            },
            "required": ["path"]
        }
    ),
    ToolDefinition(
        name="write_file",
        description="Write content to a file. Creates the file if it doesn't exist.",
        parameters={
            "type": "object",
            "properties": {
                "path": {
                    "type": "string",
                    "description": "Relative path to the file to write"
                },
                "content": {
                    "type": "string",
                    "description": "Content to write to the file"
                }
            },
            "required": ["path", "content"]
        }
    ),
    ToolDefinition(
        name="patch_file",
        description="Apply targeted edits to a file using search/replace blocks",
        parameters={
            "type": "object",
            "properties": {
                "path": {
                    "type": "string",
                    "description": "Relative path to the file to patch"
                },
                "patches": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "search": {"type": "string", "description": "Exact text to find"},
                            "replace": {"type": "string", "description": "Text to replace with"}
                        },
                        "required": ["search", "replace"]
                    },
                    "description": "List of search/replace operations"
                }
            },
            "required": ["path", "patches"]
        }
    ),
    ToolDefinition(
        name="delete_file",
        description="Delete a file at the given path",
        parameters={
            "type": "object",
            "properties": {
                "path": {
                    "type": "string",
                    "description": "Relative path to the file to delete"
                }
            },
            "required": ["path"]
        }
    ),
    ToolDefinition(
        name="run_command",
        description="Execute a shell command in the project directory",
        parameters={
            "type": "object",
            "properties": {
                "command": {
                    "type": "string",
                    "description": "The shell command to execute"
                },
                "working_dir": {
                    "type": "string",
                    "description": "Optional working directory relative to project root"
                }
            },
            "required": ["command"]
        }
    ),
    ToolDefinition(
        name="list_files",
        description="List files in a directory",
        parameters={
            "type": "object",
            "properties": {
                "path": {
                    "type": "string",
                    "description": "Relative path to directory (empty for root)"
                }
            },
            "required": []
        }
    ),
    ToolDefinition(
        name="search_files",
        description="Search for text patterns across project files",
        parameters={
            "type": "object",
            "properties": {
                "pattern": {
                    "type": "string",
                    "description": "Text or regex pattern to search for"
                },
                "file_pattern": {
                    "type": "string",
                    "description": "Optional glob pattern to filter files (e.g. '*.py')"
                }
            },
            "required": ["pattern"]
        }
    ),
    ToolDefinition(
        name="task_complete",
        description="Signal that the current task is complete",
        parameters={
            "type": "object",
            "properties": {
                "summary": {
                    "type": "string",
                    "description": "Summary of what was accomplished"
                }
            },
            "required": ["summary"]
        }
    ),
    ToolDefinition(
        name="request_help",
        description="Request clarification or additional information from the user",
        parameters={
            "type": "object",
            "properties": {
                "question": {
                    "type": "string",
                    "description": "Question or clarification needed"
                }
            },
            "required": ["question"]
        }
    ),
    ToolDefinition(
        name="web_search",
        description="Search the internet for information using DuckDuckGo. Use when you need documentation, solutions, or examples.",
        parameters={
            "type": "object",
            "properties": {
                "query": {
                    "type": "string",
                    "description": "The search query"
                },
                "max_results": {
                    "type": "integer",
                    "description": "Maximum results (default: 5, max: 10)"
                }
            },
            "required": ["query"]
        }
    ),
    ToolDefinition(
        name="read_url",
        description="Fetch and read text content from a web page URL. Use to read documentation, API references, or code examples.",
        parameters={
            "type": "object",
            "properties": {
                "url": {
                    "type": "string",
                    "description": "The URL to fetch content from"
                },
                "max_chars": {
                    "type": "integer",
                    "description": "Maximum characters to return (default: 8000)"
                }
            },
            "required": ["url"]
        }
    ),
]


SYSTEM_PROMPT = '''You are an expert AI software engineer assistant operating in a terminal environment.

## Your Capabilities

You have access to tools for:
- Reading and writing files
- Applying targeted patches to files
- Executing shell commands
- Searching codebases
- Listing directory contents
- **Searching the internet** for documentation, solutions, and examples
- **Reading web pages** to fetch detailed information

## Guidelines

1. **Understand First**: Before making changes, understand the codebase structure and existing patterns.

2. **Plan Carefully**: Break complex tasks into smaller steps. Execute them one at a time.

3. **Preserve Style**: Match existing code style, naming conventions, and patterns.

4. **Minimal Changes**: Make the smallest changes necessary to accomplish the task.

5. **Test Your Work**: After making changes, run relevant tests or build commands to verify.

6. **Handle Errors**: If a command fails or an error occurs, diagnose the issue and fix it.

7. **Use Internet When Needed**: Search the web for documentation, error solutions, or best practices when you need more information.

8. **Communicate**: Use request_help if you need clarification. Use task_complete when done.

## Response Format

Always respond with a tool call. Think through your approach, then execute the appropriate tool.

When modifying files, prefer patch_file for targeted edits over write_file for complete rewrites.

## Important

- Never expose or log sensitive information (API keys, passwords, tokens)
- Respect .gitignore patterns
- Stay within the project directory
- Ask for confirmation before destructive operations
'''


def get_tool_schemas() -> list[dict]:
    """Get OpenAI-compatible tool schemas."""
    return [
        {
            "type": "function",
            "function": {
                "name": tool.name,
                "description": tool.description,
                "parameters": tool.parameters,
            }
        }
        for tool in TOOLS
    ]


def get_anthropic_tools() -> list[dict]:
    """Get Anthropic-compatible tool schemas."""
    return [
        {
            "name": tool.name,
            "description": tool.description,
            "input_schema": tool.parameters,
        }
        for tool in TOOLS
    ]


class PromptBuilder:
    """
    Builds prompts for LLM interactions.
    
    Handles:
    - System prompt with tool definitions
    - Context formatting (project files, structure)
    - Task instructions
    - Error diagnosis prompts
    - Conversation history management
    """

    def __init__(self, project_context: Optional[ProjectContext] = None):
        self.project_context = project_context
        self.conversation_history: list[dict] = []

    def build_system_prompt(self) -> str:
        """Build the complete system prompt."""
        prompt = SYSTEM_PROMPT

        if self.project_context:
            prompt += f"\n\n## Project Context\n\n{self.project_context.get_summary()}"

        return prompt

    def build_task_prompt(self, task: str) -> str:
        """Build a prompt for a new task."""
        context_info = ""
        if self.project_context:
            # Include key file contents
            key_contents = []
            for file_info in self.project_context.files:
                if file_info.path.name in ["package.json", "requirements.txt", "pyproject.toml"]:
                    if file_info.content:
                        key_contents.append(f"### {file_info.relative_path}\n```\n{file_info.content}\n```")

            if key_contents:
                context_info = "\n\n## Key Files\n\n" + "\n\n".join(key_contents)

        return f"""## Task

{task}
{context_info}

Please analyze this task and begin working on it. Start by examining the relevant files and understanding the current state, then make the necessary changes."""

    def build_error_prompt(self, error: str, context: str = "") -> str:
        """Build a prompt for diagnosing an error."""
        return f"""## Error Occurred

The following error occurred:

```
{error}
```

{f"Context: {context}" if context else ""}

Please diagnose this error and attempt to fix it. Consider:
1. What is the root cause?
2. Which file(s) need to be modified?
3. What changes will resolve the issue?"""

    def build_continuation_prompt(self, last_result: str, was_success: bool) -> str:
        """Build a prompt to continue after a tool execution."""
        if was_success:
            return f"""## Previous Step Completed

Result:
```
{last_result[:2000]}
```

Continue with the next step of the task, or call task_complete if finished."""
        else:
            return f"""## Previous Step Failed

Error:
```
{last_result[:2000]}
```

Diagnose this issue and attempt to resolve it."""

    def add_message(self, role: str, content: str) -> None:
        """Add a message to conversation history."""
        self.conversation_history.append({"role": role, "content": content})

    def add_tool_result(self, tool_name: str, result: str, is_error: bool = False) -> None:
        """Add a tool result to conversation history."""
        self.conversation_history.append({
            "role": "tool",
            "tool_name": tool_name,
            "content": result,
            "is_error": is_error,
        })

    def get_messages(self) -> list[dict]:
        """Get the full message history for the LLM."""
        messages = [
            {"role": "system", "content": self.build_system_prompt()}
        ]
        messages.extend(self.conversation_history)
        return messages

    def clear_history(self) -> None:
        """Clear conversation history."""
        self.conversation_history = []

    def format_file_content(self, path: str, content: str, language: str = "") -> str:
        """Format file content for inclusion in prompts."""
        if not language:
            # Infer from extension
            ext_to_lang = {
                ".py": "python",
                ".js": "javascript",
                ".ts": "typescript",
                ".jsx": "jsx",
                ".tsx": "tsx",
                ".json": "json",
                ".yaml": "yaml",
                ".yml": "yaml",
                ".md": "markdown",
                ".html": "html",
                ".css": "css",
                ".sql": "sql",
                ".sh": "bash",
            }
            ext = "." + path.split(".")[-1] if "." in path else ""
            language = ext_to_lang.get(ext, "")

        return f"### {path}\n```{language}\n{content}\n```"
