from __future__ import annotations

import functools
from collections.abc import Callable
from typing import Any


def agent(
    role: str,
    goal: str,
    tools: list | None = None,
    resilience: str = "standard",
    memory: str = "session",
    token_budget: int | None = None,
    system_prompt: str | None = None,
):
    """Attach NEXUS agent metadata to a class without altering behavior."""

    def decorator(cls):
        cfg = {
            "role": role,
            "goal": goal,
            "tools": tools or [],
            "resilience": resilience,
            "memory": memory,
            "token_budget": token_budget,
            "system_prompt": system_prompt,
        }
        setattr(cls, "_nexus_agent_config", cfg)
        return cls

    return decorator


def task(
    agent: type | str,
    depends_on: list | None = None,
    loop_strategy: str = "max_iterations",
    max_iterations: int = 5,
    enables_graph_mutation: bool = False,
    tags: list[str] | None = None,
):
    """Attach NEXUS task metadata to a function."""

    def decorator(fn: Callable):
        cfg = {
            "agent": agent,
            "depends_on": depends_on or [],
            "loop_strategy": loop_strategy,
            "max_iterations": max_iterations,
            "enables_graph_mutation": enables_graph_mutation,
            "tags": tags or [],
        }

        @functools.wraps(fn)
        def wrapper(*args: Any, **kwargs: Any):
            return fn(*args, **kwargs)

        setattr(wrapper, "_nexus_task_config", cfg)
        return wrapper

    return decorator


def tool(name: str | None = None, description: str | None = None, tags: list[str] | None = None):
    """Attach NEXUS tool metadata to a function."""

    def decorator(fn: Callable):
        cfg = {
            "name": name or fn.__name__,
            "description": description or (fn.__doc__ or ""),
            "tags": tags or [],
        }

        @functools.wraps(fn)
        def wrapper(*args: Any, **kwargs: Any):
            return fn(*args, **kwargs)

        setattr(wrapper, "_nexus_tool_config", cfg)
        return wrapper

    return decorator


def is_nexus_agent(obj: Any) -> bool:
    """Check if object is decorated as NEXUS agent."""
    return hasattr(obj, "_nexus_agent_config")


def is_nexus_task(fn: Any) -> bool:
    """Check if function is decorated as NEXUS task."""
    return hasattr(fn, "_nexus_task_config")


def is_nexus_tool(fn: Any) -> bool:
    """Check if function is decorated as NEXUS tool."""
    return hasattr(fn, "_nexus_tool_config")
