"""File tools: read_file, write_file, edit_file, diff_files."""

import difflib
from salmalm.tools.tool_registry import register
from salmalm.tools.tools_common import _resolve_path


@register("read_file")
def handle_read_file(args: dict) -> str:
    """Handle read file."""
    p = _resolve_path(args["path"])
    if not p.exists():
        return f"File not found: {p}"
    # Symlink loop detection
    try:
        p.resolve(strict=True)
    except (OSError, RuntimeError):
        return f"❌ Cannot resolve path (symlink loop?): {p}"
    # Size limit: 5MB max for reading
    try:
        size = p.stat().st_size
        if size > 5 * 1024 * 1024:
            return f"❌ File too large ({size // 1024}KB). Max 5MB for read_file."
    except OSError as e:
        return f"❌ Cannot stat file: {e}"
    # Read with encoding fallback
    try:
        text = p.read_text(encoding="utf-8")
    except UnicodeDecodeError:
        text = p.read_text(encoding="latin-1")
    except OSError as e:
        return f"❌ Read error: {e}"
    lines = text.splitlines()
    offset = args.get("offset", 1) - 1
    limit = args.get("limit", len(lines))
    selected = lines[offset : offset + limit]
    return "\n".join(selected)[:50000]


@register("write_file")
def handle_write_file(args: dict) -> str:
    """Handle write file."""
    p = _resolve_path(args["path"], writing=True)
    try:
        p.parent.mkdir(parents=True, exist_ok=True)
        p.write_text(args["content"], encoding="utf-8")
    except OSError as e:
        if "No space left" in str(e) or e.errno == 28:
            return f"❌ Disk full — cannot write: {e}"
        return f"❌ Write error: {e}"
    return f"{p} ({len(args['content'])} chars)"


@register("edit_file")
def handle_edit_file(args: dict) -> str:
    """Handle edit file."""
    p = _resolve_path(args["path"], writing=True)
    text = p.read_text(encoding="utf-8")
    if args["old_text"] not in text:
        return "Text not found"
    text = text.replace(args["old_text"], args["new_text"], 1)
    p.write_text(text, encoding="utf-8")
    return f"File edited: {p}"


@register("diff_files")
def handle_diff_files(args: dict) -> str:
    """Handle diff files."""
    f1 = args.get("file1", "")
    f2 = args.get("file2", "")
    ctx = args.get("context_lines", 3)
    try:
        p1 = _resolve_path(f1)
        text1 = p1.read_text(encoding="utf-8", errors="replace").splitlines()
        label1 = f1
    except Exception as e:  # noqa: broad-except
        text1 = f1.splitlines()
        label1 = "text1"
    try:
        p2 = _resolve_path(f2)
        text2 = p2.read_text(encoding="utf-8", errors="replace").splitlines()
        label2 = f2
    except Exception as e:  # noqa: broad-except
        text2 = f2.splitlines()
        label2 = "text2"
    diff = list(difflib.unified_diff(text1, text2, fromfile=label1, tofile=label2, n=ctx))
    if not diff:
        return "Files/texts are identical."
    return "\n".join(diff[:300])
