import os
import shutil
from typing import Dict, Any, Tuple, Callable, Optional
from app.core.tools.base import BaseToolPlugin

class MeshFileExplorerTool(BaseToolPlugin):
    @property
    def name(self) -> str:
        return "mesh_file_explorer"

    def prepare_task(self, args: Dict[str, Any], context: Dict[str, Any]) -> Tuple[Optional[Callable], Dict[str, Any]]:
        action = args.get("action")
        path = args.get("path")
        content = args.get("content", "")
        node_id = args.get("node_id") or context.get("node_id")
        resolved_sid = args.get("session_id") or context.get("session_id")
        assistant = context.get("assistant")
        services = context.get("services")

        if node_id in ["hub", "server", "local"]:
            if action == "write":
                content_bytes = content.encode('utf-8') if content else b""
                return assistant.write, {"node_id": "hub", "path": path, "content": content_bytes, "session_id": resolved_sid}
            elif action == "delete":
                return assistant.rm, {"node_id": "hub", "path": path, "session_id": resolved_sid}
            else:
                def _hub_fs(**kwargs):
                    return self._execute_hub_fs(services, kwargs.get("action"), kwargs.get("path"), kwargs.get("session_id"), kwargs.get("content"))
                return _hub_fs, {"action": action, "path": path, "session_id": resolved_sid, "content": content}
        
        if action == "list":
            return assistant.ls, {"node_id": node_id, "path": path, "session_id": resolved_sid}
        elif action == "read":
            return assistant.cat, {"node_id": node_id, "path": path, "session_id": resolved_sid}
        elif action == "write":
            content_bytes = content.encode('utf-8') if content else b""
            return assistant.write, {"node_id": node_id, "path": path, "content": content_bytes, "session_id": resolved_sid}
        elif action == "delete":
            return assistant.rm, {"node_id": node_id, "path": path, "session_id": resolved_sid}
        elif action == "move":
            to_path = args.get("to_path")
            return assistant.move, {"session_id": resolved_sid, "old_path": path, "new_path": to_path}
        elif action == "copy":
            to_path = args.get("to_path")
            return assistant.copy, {"session_id": resolved_sid, "old_path": path, "new_path": to_path}
        elif action == "stat":
            return assistant.stat, {"session_id": resolved_sid, "path": path}
        
        return None, {"success": False, "error": f"Unsupported action: {action}"}

    def _execute_hub_fs(self, services, action: str, path: str, session_id: str, content: str = None) -> dict:
        orchestrator = getattr(services, "orchestrator", None)
        if not orchestrator or not orchestrator.mirror:
             return {"success": False, "error": "Ghost Mirror not available"}
        
        base = orchestrator.mirror.get_workspace_path(session_id)
        target = os.path.normpath(os.path.join(base, str(path or "").lstrip("/")))
        if not target.startswith(base):
             return {"success": False, "error": "Path traversal attempt blocked"}
             
        try:
            if action == "list":
                if not os.path.exists(target): return {"error": "Path not found"}
                files = []
                for entry in os.scandir(target):
                    if entry.name in [".cortex_sync"] and path in [".", "", "/"]:
                        continue
                    files.append({
                        "path": os.path.relpath(entry.path, base),
                        "name": entry.name,
                        "is_dir": entry.is_dir(),
                        "size": entry.stat().st_size if entry.is_file() else 0
                    })
                return {"files": files, "path": path}
            elif action == "read":
                if not os.path.exists(target): return {"error": "File not found"}
                with open(target, "r", encoding="utf-8", errors="ignore") as f:
                    return {"content": f.read(), "path": path}
            elif action == "write":
                os.makedirs(os.path.dirname(target), exist_ok=True)
                with open(target, "w", encoding="utf-8") as f:
                    f.write(content or "")
                return {"success": True}
            elif action == "delete":
                if os.path.islink(target):
                    os.unlink(target)
                elif os.path.isdir(target):
                    shutil.rmtree(target)
                elif os.path.exists(target):
                    os.remove(target)
                return {"success": True}
        except Exception as e:
            return {"error": str(e)}
        return {"error": f"Unknown action: {action}"}
