"""LS tool — list directory contents."""

from __future__ import annotations

import os
from typing import Any

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


LS_TOOL_NAME = "ls"
LS_TOOL_DESCRIPTION = "List directory contents."

LS_TOOL_PARAMETERS = {
    "type": "object",
    "properties": {
        "path": {"type": "string", "description": "Directory to list"},
        "limit": {"type": "integer", "description": "Max entries (default: 500)"},
    },
}


def create_ls_tool(cwd: str | None = None) -> AgentTool:
    """Create an ls tool for listing directory contents."""

    class LsTool(AgentTool):
        def __init__(self) -> None:
            super().__init__(
                name=LS_TOOL_NAME,
                description=LS_TOOL_DESCRIPTION,
                parameters=LS_TOOL_PARAMETERS,
            )
            self.label = "LS"

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

            target = path or cwd or os.getcwd()
            if cwd and not os.path.isabs(target):
                target = os.path.join(cwd, target)

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

            if not os.path.isdir(target):
                return AgentToolResult(
                    content=[TextContent(type="text", text=f"Not a directory: {target}")]
                )

            try:
                entries = os.listdir(target)
            except Exception as e:
                return AgentToolResult(
                    content=[TextContent(type="text", text=f"Error listing directory: {e}")]
                )

            # Sort case-insensitive alphabetically
            entries.sort(key=lambda x: x.lower())

            # Mark directories with /
            lines: list[str] = []
            for entry in entries[:limit]:
                full = os.path.join(target, entry)
                suffix = "/" if os.path.isdir(full) else ""
                lines.append(entry + suffix)

            result = "\n".join(lines) if lines else "(empty directory)"
            tr = truncate_head(result)

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

    return LsTool()
