"""Read tool — reads files and images."""

from __future__ import annotations

import mimetypes
import os
from typing import Any

from pi_agents.agent.types import AgentTool, AgentToolResult
from pi_agents.ai.types import ImageContent, TextContent
from pi_agents.coding_agent.tools.truncate import truncate_head, DEFAULT_MAX_LINES, DEFAULT_MAX_BYTES


READ_TOOL_NAME = "read"
READ_TOOL_DESCRIPTION = "Read the contents of a file. Supports text files and images."

READ_TOOL_PARAMETERS = {
    "type": "object",
    "properties": {
        "path": {"type": "string", "description": "File path to read"},
        "offset": {"type": "integer", "description": "Line number to start from (1-indexed)"},
        "limit": {"type": "integer", "description": "Maximum number of lines to read"},
    },
    "required": ["path"],
}

_IMAGE_EXTENSIONS = {".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp", ".svg"}


def _detect_image_mime(path: str) -> str | None:
    """Detect image MIME type from file extension."""
    ext = os.path.splitext(path)[1].lower()
    if ext in _IMAGE_EXTENSIONS:
        mime, _ = mimetypes.guess_type(path)
        return mime
    return None


def create_read_tool(cwd: str | None = None) -> AgentTool:
    """Create a read tool for reading files."""

    class ReadTool(AgentTool):
        def __init__(self) -> None:
            super().__init__(
                name=READ_TOOL_NAME,
                description=READ_TOOL_DESCRIPTION,
                parameters=READ_TOOL_PARAMETERS,
            )
            self.label = "Read"

        async def execute(
            self,
            tool_call_id: str,
            params: dict[str, Any],
            signal: Any = None,
            on_update: Any = None,
        ) -> AgentToolResult:
            path = params.get("path", "")
            offset = params.get("offset")
            limit = params.get("limit")

            # Resolve path
            if cwd and not os.path.isabs(path):
                path = os.path.join(cwd, path)

            if not os.path.exists(path):
                return AgentToolResult(
                    content=[TextContent(type="text", text=f"File not found: {path}")]
                )

            # Check for image
            mime = _detect_image_mime(path)
            if mime:
                import base64
                with open(path, "rb") as f:
                    data = base64.b64encode(f.read()).decode("ascii")
                return AgentToolResult(
                    content=[ImageContent(type="image", source=data, mime_type=mime)]
                )

            # Read text file
            try:
                with open(path, "r", encoding="utf-8", errors="replace") as f:
                    content = f.read()
            except Exception as e:
                return AgentToolResult(
                    content=[TextContent(type="text", text=f"Error reading file: {e}")]
                )

            lines = content.split("\n")

            # Apply offset (1-indexed)
            if offset is not None and offset > 1:
                lines = lines[offset - 1:]

            # Apply limit
            max_lines = limit if limit else DEFAULT_MAX_LINES
            if len(lines) > max_lines:
                lines = lines[:max_lines]

            result_text = "\n".join(lines)

            # Truncate if too large
            tr = truncate_head(result_text)
            details: dict[str, Any] | None = None
            if tr.truncated:
                details = {
                    "truncated": True,
                    "truncatedBy": tr.truncated_by,
                    "totalLines": tr.total_lines,
                    "totalBytes": tr.total_bytes,
                }
                if offset and offset > 1:
                    details["nextOffset"] = (offset or 1) + tr.output_lines

            return AgentToolResult(
                content=[TextContent(type="text", text=tr.content)],
                details=details,
            )

    return ReadTool()
