"""Text editor tool: view, create, and edit files directly."""

import os

from genworker.config import log

# Track last saved content per path for potential recovery
_file_history: dict[str, str] = {}


def execute_text_editor(inp: dict) -> str:
    command = inp.get("command", "")
    path    = inp.get("path", "")
    log.info(f"⚡  text_editor/{command} | path={path}")

    try:
        if command == "view":
            if not path:
                return "Error: path is required"
            if os.path.isdir(path):
                items   = sorted(os.listdir(path))
                listing = "\n".join(items[:300])
                return f"Directory listing of {path}:\n{listing}"
            if not os.path.exists(path):
                return f"Error: file not found: {path}"
            with open(path, "r", encoding="utf-8", errors="replace") as f:
                lines = f.readlines()
            view_range = inp.get("view_range")
            if view_range:
                start, end = int(view_range[0]), int(view_range[1])
                lines      = lines[start - 1:end]
                start_num  = start
            else:
                start_num = 1
            if len(lines) > 500:
                lines = lines[:250] + ["... [TRUNCATED] ...\n"] + lines[-250:]
            numbered = [f"{start_num + i:>5}\t{line}" for i, line in enumerate(lines)]
            return "".join(numbered)

        elif command == "create":
            file_text = inp.get("file_text", "")
            if not path:
                return "Error: path is required"
            dir_name = os.path.dirname(path)
            if dir_name:
                os.makedirs(dir_name, exist_ok=True)
            with open(path, "w", encoding="utf-8") as f:
                f.write(file_text)
            return f"File created successfully: {path} ({len(file_text)} chars)"

        elif command == "str_replace":
            old_str = inp.get("old_str", "")
            new_str = inp.get("new_str", "")
            if not path or not os.path.exists(path):
                return f"Error: file not found: {path}"
            with open(path, "r", encoding="utf-8") as f:
                content = f.read()
            count = content.count(old_str)
            if count == 0:
                snippet_start = max(0, len(content) // 2 - 200)
                snippet       = content[snippet_start:snippet_start + 400]
                return (
                    f"Error: old_str not found in {path}. "
                    f"File has {len(content)} chars. "
                    f"Middle snippet: ...{snippet}..."
                )
            if count > 1:
                return f"Error: old_str found {count} times (need exactly 1). Make the string more specific."
            _file_history[path] = content
            content = content.replace(old_str, new_str, 1)
            with open(path, "w", encoding="utf-8") as f:
                f.write(content)
            return f"Replacement successful in {path}"

        elif command == "insert":
            insert_line = int(inp.get("insert_line", 0))
            new_str     = inp.get("new_str", "")
            if not path or not os.path.exists(path):
                return f"Error: file not found: {path}"
            with open(path, "r", encoding="utf-8") as f:
                content = f.read()
            _file_history[path] = content
            lines = content.splitlines(keepends=True)
            if insert_line < 0 or insert_line > len(lines):
                return f"Error: insert_line {insert_line} out of range (0-{len(lines)})"
            lines.insert(insert_line, new_str + "\n")
            with open(path, "w", encoding="utf-8") as f:
                f.writelines(lines)
            return f"Inserted text at line {insert_line} in {path}"

        elif command == "undo_edit":
            return "Error: undo_edit is not supported. Use str_replace to make corrections instead."

        else:
            return f"Unknown command: {command}"

    except Exception as e:
        log.error(f"Text editor error: {e}")
        return f"Error: {e}"
