class _DummyMeta(dict):
    def __getattr__(self, item):
        try:
            return self[item]
        except KeyError as exc:
            raise AttributeError(item) from exc

    model_extra = property(lambda self: self)

    def model_dump(self, exclude_none=True):
        if not exclude_none:
            return dict(self)
        return {k: v for k, v in self.items() if v is not None}


class DummyContext:
    """Mock context object for testing"""

    def __init__(self, **meta):
        import uuid
        self.log_info = []
        self.log_warning = []
        self.log_error = []
        self._meta = _DummyMeta(meta)
        # Give each context a unique session_id to avoid state leakage between tests
        self.session_id = str(uuid.uuid4())
        # Add state storage to mimic FastMCP context state
        self._state = {}

        class _RequestContext:
            def __init__(self, meta):
                self.meta = meta

        self.request_context = _RequestContext(self._meta)

    async def info(self, message):
        self.log_info.append(message)

    async def warning(self, message):
        self.log_warning.append(message)

    # Some code paths call warn(); treat it as an alias of warning()
    async def warn(self, message):
        await self.warning(message)

    async def error(self, message):
        self.log_error.append(message)

    async def set_state(self, key, value):
        """Set state value (mimics FastMCP context.set_state)"""
        self._state[key] = value

    async def get_state(self, key, default=None):
        """Get state value (mimics FastMCP context.get_state)"""
        return self._state.get(key, default)


class DummyMCP:
    """Mock MCP server for testing tool registration patterns."""

    def __init__(self):
        self.tools = {}

    def tool(self, *args, **kwargs):
        def deco(fn):
            self.tools[fn.__name__] = fn
            return fn
        return deco


def setup_script_tools():
    """
    Setup script-related tools for testing.

    Returns a dict mapping tool names to their async handler functions.
    Useful for testing parameter serialization and SDK behavior.
    """
    mcp = DummyMCP()
    # Import tools to trigger decorator-based registration
    import services.tools.manage_script
    from services.registry import get_registered_tools

    for tool_info in get_registered_tools():
        name = tool_info['name']
        if any(k in name for k in ['script', 'apply_text', 'create_script',
                                    'delete_script', 'validate_script', 'get_sha']):
            mcp.tools[name] = tool_info['func']
    return mcp.tools
