"""Edit file tool — string replacement in files."""

from __future__ import annotations

from pathlib import Path
from typing import Any

from tsumugi.tools.base import BaseTool, PermissionLevel, ToolSpec


class EditFileTool(BaseTool):
    """Edit a file by replacing a specific string."""

    def spec(self) -> ToolSpec:
        return ToolSpec(
            name="edit_file",
            description=(
                "Edit a file by replacing an exact string match. "
                "The old_string must be unique in the file (or use replace_all). "
                "Preserves exact indentation."
            ),
            parameters={
                "type": "object",
                "properties": {
                    "file_path": {
                        "type": "string",
                        "description": "Path to the file to edit",
                    },
                    "old_string": {
                        "type": "string",
                        "description": "The exact string to find and replace",
                    },
                    "new_string": {
                        "type": "string",
                        "description": "The replacement string",
                    },
                    "replace_all": {
                        "type": "boolean",
                        "description": "Replace all occurrences. Default: false",
                    },
                },
                "required": ["file_path", "old_string", "new_string"],
            },
            permission=PermissionLevel.WRITE,
        )

    def execute(self, **kwargs: Any) -> str:
        file_path = kwargs["file_path"]
        old_string = kwargs["old_string"]
        new_string = kwargs["new_string"]
        replace_all = kwargs.get("replace_all", False)

        path = Path(file_path).resolve()

        if not path.exists():
            return f"Error: File not found: {path}"
        if not path.is_file():
            return f"Error: Not a file: {path}"

        try:
            content = path.read_text(encoding="utf-8")
        except OSError as e:
            return f"Error reading file: {e}"

        if old_string == new_string:
            return "Error: old_string and new_string are identical"

        count = content.count(old_string)
        if count == 0:
            return "Error: old_string not found in file"

        if count > 1 and not replace_all:
            return (
                f"Error: old_string found {count} times. "
                "Use replace_all=true or provide more context to make it unique."
            )

        if replace_all:
            new_content = content.replace(old_string, new_string)
            replaced = count
        else:
            new_content = content.replace(old_string, new_string, 1)
            replaced = 1

        try:
            path.write_text(new_content, encoding="utf-8")
        except OSError as e:
            return f"Error writing file: {e}"

        return f"Successfully replaced {replaced} occurrence(s) in {path}"
