"""Resource class for hierarchical API access.

This module provides the Resource class which enables a fluent, dot-notation interface
for accessing the CATAPA API path hierarchy.
"""

import threading
from typing import Any, Dict, List, Optional

from catapa.resource_node import ResourceNode


class Resource:
    """Represents a node in the CATAPA API hierarchy at runtime.

    Enables dynamic access to child resources and API methods through __getattr__.
    Supports 'hybrid' nodes that act as both a namespace for child resources and
    an API endpoint with its own methods.
    """

    def __init__(self, node: ResourceNode, api_client: Any) -> None:
        """Initialize a Resource instance.

        Args:
            node: Metadata node for this resource
            api_client: CATAPA client instance for API calls
        """
        # Initialize attributes needed by __getattr__ BEFORE anything that might trigger it
        self._resource_cache: Dict[str, Resource] = {}
        self._resource_cache_lock = threading.Lock()
        self._attr_index: Dict[str, ResourceNode] = {child.attribute_name: child for child in node.children}

        self._node = node
        self._api_client = api_client
        self._api_instance: Optional[Any] = None
        self._api_lock = threading.Lock()
        self.__doc__ = node.description

    def _get_api_instance(self) -> Any:
        """Lazily instantiate the underlying API class (thread-safe)."""
        if self._api_instance is None:
            with self._api_lock:
                if self._api_instance is None:
                    # Import here to avoid circular dependency
                    from openapi_client import api as api_module  # noqa: PLC0415

                    api_class_name = self._node.get_api_class_name()
                    if not hasattr(api_module, api_class_name):
                        raise AttributeError(f"API class '{api_class_name}' not found")
                    api_class = getattr(api_module, api_class_name)
                    self._api_instance = api_class(self._api_client)
        return self._api_instance

    def __getattr__(self, name: str) -> Any:
        """Dynamically access child resources or API methods."""
        # 1. Check for child resources first
        child = self._attr_index.get(name)
        if child is not None:
            if name not in self._resource_cache:
                with self._resource_cache_lock:
                    if name not in self._resource_cache:
                        self._resource_cache[name] = Resource(child, self._api_client)
            return self._resource_cache[name]

        # 2. If it's an API resource, delegate to the API instance
        if self._node.is_api:
            api_instance = self._get_api_instance()
            if hasattr(api_instance, name):
                return getattr(api_instance, name)

        raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")

    def __dir__(self) -> List[str]:
        """List available child resources and API methods for IDE autocomplete.

        Returns:
            List of child attribute names and API methods
        """
        # Start with standard attributes
        attrs = list(super().__dir__())

        # Add child resource names
        attrs.extend(child.attribute_name for child in self._node.children)

        # If it's an API, add API methods
        if self._node.is_api:
            api_instance = self._get_api_instance()
            attrs.extend(dir(api_instance))

        return sorted(set(attrs))

    def __repr__(self) -> str:
        """Return string representation of the Resource."""
        return f"<Resource {self._node.namespace} (is_api={self._node.is_api})>"
