"""
Nexus = filesystem/context plane.

Nexus SDK - clean programmatic interface for third-party tools.

This module provides a clean, stable API for building custom tools and interfaces
on top of Nexus, without any CLI dependencies. Use this SDK to build:
- Custom GUIs and TUIs
- Web interfaces
- IDE plugins
- Custom automation tools
- Language bindings

The SDK interface is stable and semantic-versioned separately from CLI changes.

Quick Start (Local - Verified):
    >>> from nexus.sdk import connect
    >>>
    >>> nx = connect(config={"profile": "embedded", "data_dir": "./nexus-data"})
    >>> nx.sys_write("/workspace/file.txt", b"Hello World")
    >>> content = nx.sys_read("/workspace/file.txt")

Quick Start (Remote):
    >>> from nexus.sdk import connect
    >>>
    >>> # Start server first:
    >>> #   export NEXUS_GRPC_PORT=2126
    >>> #   nexusd --host 0.0.0.0 --port 2026
    >>> # Set environment: export NEXUS_URL=http://localhost:2026
    >>>
    >>> # Connect to Nexus server (thin remote client)
    >>> nx = connect(config={"profile": "remote", "url": "http://localhost:2026"})
    >>>
    >>> # File operations
    >>> nx.sys_write("/workspace/file.txt", b"Hello World")
    >>> content = nx.sys_read("/workspace/file.txt")
    >>> nx.sys_unlink("/workspace/file.txt")
    >>>
    >>> # Discovery
    >>> files = nx.sys_readdir("/workspace", recursive=True)
    >>> python_files = nx.glob("**/*.py")
    >>> todos = nx.grep("TODO", file_pattern="**/*.py")

Configuration:
    >>> # Remote mode with auto-discovery
    >>> # Checks NEXUS_URL and NEXUS_API_KEY environment variables
    >>> nx = connect(config={"profile": "remote"})
    >>>
    >>> # Server mode with explicit config
    >>> nx = connect(config={
    ...     "profile": "remote",
    ...     "url": "http://localhost:2026",
    ...     "api_key": "your-api-key"
    ... })
    >>>
    >>> # Local mode
    >>> nx = connect(config={
    ...     "profile": "embedded",
    ...     "data_dir": "./nexus-data"
    ... })
    >>>
    >>> # From config file
    >>> nx = connect(config="/path/to/nexus.yaml")
"""

__all__ = [
    # Main entry point
    "connect",
    # Configuration
    "Config",
    "load_config",
    # Core interfaces
    "Filesystem",
    "NexusFS",
    # Backends
    "Backend",
    "CASLocalBackend",
    "PathLocalBackend",
    "CASGCSBackend",
    # Exceptions
    "NexusError",
    "FileNotFoundError",
    "PermissionError",
    "BackendError",
    "InvalidPathError",
    "MetadataError",
    "ValidationError",
    # Permissions
    "OperationContext",
    "PermissionEnforcer",
    # ReBAC
    "ReBACManager",
    "ReBACTuple",
    "Entity",
    "WILDCARD_SUBJECT",
    "CheckResult",
    "GraphLimitExceeded",
]

# Re-export from core modules with cleaner names
from pathlib import Path
from typing import Any, Union

from nexus.backends.base.backend import Backend
from nexus.backends.storage.cas_gcs import CASGCSBackend
from nexus.backends.storage.cas_local import CASLocalBackend
from nexus.backends.storage.path_local import PathLocalBackend
from nexus.config import NexusConfig as Config
from nexus.config import load_config
from nexus.contracts.exceptions import (
    BackendError,
    InvalidPathError,
    MetadataError,
    NexusError,
    ValidationError,
)
from nexus.contracts.exceptions import (
    NexusFileNotFoundError as FileNotFoundError,
)
from nexus.contracts.exceptions import (
    NexusPermissionError as PermissionError,
)

# ReBAC types canonical in contracts — always available (#3230)
from nexus.contracts.rebac_types import WILDCARD_SUBJECT, CheckResult, Entity, GraphLimitExceeded
from nexus.contracts.types import OperationContext
from nexus.core.nexus_fs import NexusFS
from nexus.core.nexus_fs import NexusFS as Filesystem

# =============================================================================
# LAZY IMPORTS for optional bricks (#3230)
# =============================================================================
# These ReBAC implementation types require the rebac brick to be installed.
# They are loaded on-demand via __getattr__ to allow `import nexus.sdk` to
# succeed without bricks.rebac installed.

_LAZY_REBAC_IMPORTS: dict[str, tuple[str, str]] = {
    "ReBACTuple": ("nexus.bricks.rebac.domain", "ReBACTuple"),
    "PermissionEnforcer": ("nexus.bricks.rebac.enforcer", "PermissionEnforcer"),
    "ReBACManager": ("nexus.bricks.rebac.manager", "ReBACManager"),
}

_lazy_imports_cache: dict[str, Any] = {}


def __getattr__(name: str) -> Any:
    """Lazy import for optional brick dependencies.

    ReBAC implementation types (ReBACTuple, PermissionEnforcer, ReBACManager)
    are loaded on first access. If the rebac brick is not installed, a clear
    ImportError is raised.
    """
    if name in _lazy_imports_cache:
        return _lazy_imports_cache[name]

    if name in _LAZY_REBAC_IMPORTS:
        module_path, attr_name = _LAZY_REBAC_IMPORTS[name]
        import importlib

        try:
            module = importlib.import_module(module_path)
        except ModuleNotFoundError as exc:
            raise ImportError(
                f"nexus.sdk.{name} requires the ReBAC brick. "
                f"Install it with: pip install nexus[rebac]"
            ) from exc
        value = getattr(module, attr_name)
        _lazy_imports_cache[name] = value
        return value

    raise AttributeError(f"module 'nexus.sdk' has no attribute {name!r}")


def __dir__() -> list[str]:
    """Include lazy imports in dir() for discoverability."""
    module_attrs = list(globals().keys())
    module_attrs.extend(_LAZY_REBAC_IMPORTS.keys())
    return module_attrs


async def connect(
    config: str | Path | dict | Config | None = None,
) -> Filesystem:
    """
    Connect to Nexus filesystem.

    This is the main SDK entry point. It auto-detects the deployment mode
    from configuration and returns the appropriate client.

    Args:
        config: Configuration source:
            - None: Auto-discover from environment/files (default)
            - str/Path: Path to config file
            - dict: Configuration dictionary
            - Config: Already loaded config object

    Returns:
        Filesystem instance implementing the Nexus interface.

    Raises:
        ValueError: If configuration is invalid
        NotImplementedError: If mode is not yet implemented

    Examples:
        >>> # Use local backend (default)
        >>> nx = connect()
        >>> nx.sys_write("/workspace/file.txt", b"Hello World")
        >>> content = nx.sys_read("/workspace/file.txt")

        >>> # Use GCS backend
        >>> nx = connect(config={
        ...     "backend": "gcs",
        ...     "gcs_bucket_name": "my-bucket",
        ... })

        >>> # From config file
        >>> nx = connect(config="/path/to/nexus.yaml")
    """
    # Delegate to the main connect function from nexus package
    from nexus import connect as nexus_connect

    return nexus_connect(config)
