"""
mizan - Django + React unified framework

Server functions are the core primitive. Everything else builds on them.

## Quick Start

### 1. urls.py - HTTP endpoint
```python
from mizan import urls as mizan_urls

urlpatterns = [
    path('api/mizan/', include(mizan_urls)),
]
```

### 2. asgi.py - WebSocket support (optional)
```python
from mizan import wrap_asgi
from django.core.asgi import get_asgi_application

application = wrap_asgi(get_asgi_application())
```

### 3. Define server functions
```python
# apps/myapp/clients.py
from mizan import client
from pydantic import BaseModel

class EchoOutput(BaseModel):
    message: str

# HTTP-only function (default)
@client
def echo(request, text: str) -> EchoOutput:
    return EchoOutput(message=f"Echo: {text}")

# Global context (singleton, SSR-hydrated)
@client(context='global')
def current_user(request) -> UserOutput:
    return UserOutput(email=request.user.email)

# WebSocket-enabled for real-time
@client(websocket=True)
def send_message(request, room_id: int, text: str) -> MessageOutput:
    return MessageOutput(...)
```

### 4. Auto-discover in apps.py
```python
class MyAppConfig(AppConfig):
    def ready(self):
        from mizan.setup import mizan_clients
        mizan_clients('apps')
```

### 5. Frontend - generate types and use
```bash
npm run schemas
```
```tsx
import { useEcho, useCurrentUser } from '@/api'

const user = useCurrentUser()
const echo = useEcho()
await echo({ text: 'hello' })
```

## What You Get

| Backend                            | Frontend              | Transport  |
|------------------------------------|-----------------------|------------|
| `@client`                          | `useXxx()` hook       | HTTP       |
| `@client(context='global')`        | `useXxx()` + SSR      | HTTP       |
| `@client(context='local')`         | `<XxxProvider>` + hook| HTTP       |
| `@client(websocket=True)`          | `useXxx()` hook       | WebSocket  |
| `@compose(...)`                    | `<XxxProvider>` combined | varies  |
| `mizanFormMixin`                  | `useXxxForm()` + Zod  | HTTP       |
| `ReactChannel`                     | `useXxxChannel()`     | WebSocket  |
"""

# All imports at module level (sorted)
from . import channels
from . import client as client_module
from . import export
from . import forms
from . import setup
from .channels import ReactChannel
from .channels import register as register_channel
from .client import ComposedContext, GlobalContext, ReactContext, ServerFunction, client, compose

# Shape is lazy-loaded via __getattr__ because django_readers
# imports contenttypes, which can't happen during apps.populate()
from .setup import (
    mizan_clients,
    mizan_module,
    get_channel,
    get_function,
    register,
    register_as,
)


def __getattr__(name):
    """Lazy loading for modules that can't be imported at app load time."""
    if name == "urls":
        from .urls import urlpatterns as mizan_patterns

        return mizan_patterns
    if name == "Shape":
        from .shapes import Shape

        return Shape
    raise AttributeError(f"module {__name__!r} has no attribute {name!r}")


def wrap_asgi(http_application):
    """
    Wrap an ASGI application with mizan WebSocket support.

    Usage in asgi.py:
        from django.core.asgi import get_asgi_application
        from mizan import wrap_asgi

        application = wrap_asgi(get_asgi_application())

    This adds:
    - WebSocket routing at /ws/ for RPC and channels
    - Authentication middleware for WebSocket connections
    """
    try:
        from channels.auth import AuthMiddlewareStack
        from channels.routing import ProtocolTypeRouter, URLRouter
        from django.urls import path
    except ImportError:
        raise ImportError(
            "django-channels is required for WebSocket support.\n"
            "Install with: pip install channels channels-redis\n"
            "Add 'channels' to INSTALLED_APPS and configure CHANNEL_LAYERS."
        )

    from .channels.connection import DjangoReactConsumer

    return ProtocolTypeRouter(
        {
            "http": http_application,
            "websocket": AuthMiddlewareStack(
                URLRouter(
                    [
                        path("ws/", DjangoReactConsumer.as_asgi()),
                    ]
                )
            ),
        }
    )


__all__ = [
    # Decorators & Contexts
    "client",
    "compose",
    "ReactContext",
    "GlobalContext",
    "ServerFunction",
    "ComposedContext",
    # Setup
    "mizan_clients",
    "mizan_module",
    "register",
    "register_as",
    "get_function",
    "get_channel",
    # ASGI
    "wrap_asgi",
    # Channels
    "ReactChannel",
    "register_channel",
    # Shapes
    "Shape",
    # Submodules
    "client_module",
    "setup",
    "forms",
    "channels",
    "export",
]
