"""
Debug Issue tool - Root cause analysis and debugging assistance
"""

from typing import TYPE_CHECKING, Any, Optional

from pydantic import Field

if TYPE_CHECKING:
    from tools.models import ToolModelCategory

from config import TEMPERATURE_ANALYTICAL
from systemprompts import DEBUG_ISSUE_PROMPT

from .base import BaseTool, ToolRequest


class DebugIssueRequest(ToolRequest):
    """Request model for debug tool"""

    prompt: str = Field(..., description="Error message, symptoms, or issue description")
    error_context: Optional[str] = Field(None, description="Stack trace, logs, or additional error context")
    files: Optional[list[str]] = Field(
        None,
        description="Files or directories that might be related to the issue (must be absolute paths)",
    )
    runtime_info: Optional[str] = Field(None, description="Environment, versions, or runtime information")
    previous_attempts: Optional[str] = Field(None, description="What has been tried already")


class DebugIssueTool(BaseTool):
    """Advanced debugging and root cause analysis tool"""

    def get_name(self) -> str:
        return "debug"

    def get_description(self) -> str:
        return (
            "DEBUG - Root cause analysis. Share all diagnostic files, logs, traces. "
            "1M token capacity. More context = better analysis."
        )

    def get_input_schema(self) -> dict[str, Any]:
        schema = {
            "type": "object",
            "properties": {
                "prompt": {
                    "type": "string",
                    "description": "Error message, symptoms, or issue description",
                },
                "model": self.get_model_field_schema(),
                "error_context": {
                    "type": "string",
                    "description": "Stack trace, logs, or additional error context",
                },
                "files": {
                    "type": "array",
                    "items": {"type": "string"},
                    "description": "Files or directories that might be related to the issue (must be absolute paths)",
                },
                "runtime_info": {
                    "type": "string",
                    "description": "Environment, versions, or runtime information",
                },
                "previous_attempts": {
                    "type": "string",
                    "description": "What has been tried already",
                },
                "temperature": {
                    "type": "number",
                    "description": "Temperature (0-1, default 0.2 for accuracy)",
                    "minimum": 0,
                    "maximum": 1,
                },
                "thinking_mode": {
                    "type": "string",
                    "enum": ["minimal", "low", "medium", "high", "max"],
                    "description": "Thinking depth: minimal (0.5% of model max), low (8%), medium (33%), high (67%), max (100% of model max)",
                },
                "use_websearch": {
                    "type": "boolean",
                    "description": "Enable web search for documentation, best practices, and current information. Particularly useful for: brainstorming sessions, architectural design discussions, exploring industry best practices, working with specific frameworks/technologies, researching solutions to complex problems, or when current documentation and community insights would enhance the analysis.",
                    "default": True,
                },
                "file_handling_mode": {
                    "type": "string",
                    "enum": ["embedded", "summary", "reference"],
                    "default": "embedded",
                    "description": "How to handle file content in responses. 'embedded' includes full content (default), 'summary' returns only summaries to save tokens, 'reference' stores files and returns IDs.",
                },
                "continuation_id": {
                    "type": "string",
                    "description": "Thread continuation ID for multi-turn conversations. Can be used to continue conversations across different tools. Only provide this if continuing a previous conversation thread.",
                },
            },
            "required": ["prompt"] + (["model"] if self.is_effective_auto_mode() else []),
        }

        return schema

    def get_system_prompt(self) -> str:
        return DEBUG_ISSUE_PROMPT

    def get_default_temperature(self) -> float:
        return TEMPERATURE_ANALYTICAL

    # Line numbers are enabled by default from base class for precise error location

    def get_model_category(self) -> "ToolModelCategory":
        """Debug requires deep analysis and reasoning"""
        from tools.models import ToolModelCategory

        return ToolModelCategory.EXTENDED_REASONING

    def get_request_model(self):
        return DebugIssueRequest

    async def prepare_prompt(self, request: DebugIssueRequest) -> str:
        """Prepare the debugging prompt"""
        # Check for prompt.txt in files
        prompt_content, updated_files = self.handle_prompt_file(request.files)

        # If prompt.txt was found, use it as prompt or error_context
        if prompt_content:
            if not request.prompt or request.prompt == "":
                request.prompt = prompt_content
            else:
                request.error_context = prompt_content

        # Check user input sizes at MCP transport boundary (before adding internal content)
        size_check = self.check_prompt_size(request.prompt)
        if size_check:
            from tools.models import ToolOutput

            raise ValueError(f"MCP_SIZE_CHECK:{ToolOutput(**size_check).model_dump_json()}")

        if request.error_context:
            size_check = self.check_prompt_size(request.error_context)
            if size_check:
                from tools.models import ToolOutput

                raise ValueError(f"MCP_SIZE_CHECK:{ToolOutput(**size_check).model_dump_json()}")

        # Update request files list
        if updated_files is not None:
            request.files = updated_files

        # Build context sections
        context_parts = [f"=== ISSUE DESCRIPTION ===\n{request.prompt}\n=== END DESCRIPTION ==="]

        if request.error_context:
            context_parts.append(f"\n=== ERROR CONTEXT/STACK TRACE ===\n{request.error_context}\n=== END CONTEXT ===")

        if request.runtime_info:
            context_parts.append(f"\n=== RUNTIME INFORMATION ===\n{request.runtime_info}\n=== END RUNTIME ===")

        if request.previous_attempts:
            context_parts.append(f"\n=== PREVIOUS ATTEMPTS ===\n{request.previous_attempts}\n=== END ATTEMPTS ===")

        # Add relevant files if provided
        if request.files:
            # Use centralized file processing logic
            continuation_id = getattr(request, "continuation_id", None)
            file_content, processed_files, file_references = self._prepare_file_content_for_prompt(
                request.files, continuation_id, "Code"
            )

            # Store file references for response formatting
            if file_references:
                self._store_file_references(file_references)
            self._actually_processed_files = processed_files

            if file_content:
                context_parts.append(f"\n=== RELEVANT CODE ===\n{file_content}\n=== END CODE ===")

        full_context = "\n".join(context_parts)

        # Check token limits
        self._validate_token_limit(full_context, "Context")

        # Add web search instruction if enabled
        websearch_instruction = self.get_websearch_instruction(
            request.use_websearch,
            """When debugging issues, consider if searches for these would help:
- The exact error message to find known solutions
- Framework-specific error codes and their meanings
- Similar issues in forums, GitHub issues, or Stack Overflow
- Workarounds and patches for known bugs
- Version-specific issues and compatibility problems""",
        )

        # Combine everything
        full_prompt = f"""{self.get_system_prompt()}{websearch_instruction}

{full_context}

Please debug this issue following the structured format in the system prompt.
Focus on finding the root cause and providing actionable solutions."""

        return full_prompt

    def format_response(self, response: str, request: DebugIssueRequest, model_info: Optional[dict] = None) -> str:
        """Format the debugging response"""
        # Get the friendly model name
        model_name = "the model"
        if model_info and model_info.get("model_response"):
            model_name = model_info["model_response"].friendly_name or "the model"

        return f"""{response}

---

**Next Steps:** Evaluate {model_name}'s recommendations, synthesize the best fix considering potential regressions, and if the root cause has been clearly identified, proceed with implementing the potential fixes."""
