"""
OMNIWEB Complete Example - All features combined!

This example demonstrates:
- Zero-config Authentication
- Real-time WebSockets
- Auto-Admin panel
- Desktop Mode
- ORM (DATAVOXEL)
- Validation (INTEGRIUM)
- HTTP Client (VELOCRIUM)
"""

from omniweb import OmniWeb, Model, validate, Field
from omniweb.auth import enable_auth, requires_auth
from omniweb.realtime import enable_realtime, broadcast
from omniweb.admin import AutoAdmin
from omniweb.desktop import run_as_desktop
import sys

# Create app
app = OmniWeb(
    title="Complete OMNIWEB App",
    version="1.0.0",
    description="Full-featured app with all OMNIWEB capabilities",
    debug=True
)

# Enable authentication
auth = enable_auth(
    app,
    enable_magic_links=True,
    enable_2fa=True,
)

# Enable real-time
realtime = enable_realtime(app)

# Define models
class User(Model):
    __table__ = "users"

class Post(Model):
    __table__ = "posts"

class Comment(Model):
    __table__ = "comments"

# Setup admin
admin = AutoAdmin(app)
admin.register(User)
admin.register(Post)
admin.register(Comment)

# Routes
@app.get("/")
async def home():
    """Homepage."""
    return {
        "app": "Complete OMNIWEB App",
        "features": {
            "auth": "✅ Zero-config authentication",
            "realtime": "✅ WebSocket + SSE",
            "admin": "✅ Auto-generated admin panel",
            "desktop": "✅ Desktop mode ready",
            "orm": "✅ DATAVOXEL ORM",
            "validation": "✅ INTEGRIUM validation",
            "http_client": "✅ VELOCRIUM HTTP client"
        },
        "endpoints": {
            "auth": "/auth/*",
            "admin": "/admin",
            "websocket": "/ws",
            "api": "/api/*"
        }
    }

# Public API
@app.get("/api/posts")
async def list_posts(limit: int = 10):
    """List all posts (public)."""
    posts = await Post.all()
    return {
        "posts": [p.dict() for p in posts[:limit]],
        "total": len(posts)
    }

@app.get("/api/posts/{id}")
async def get_post(id: int):
    """Get post by ID (public)."""
    post = await Post.get(id=id)
    if not post:
        return {"error": "Post not found"}, 404
    return post.dict()

# Protected API (requires auth)
@app.post("/api/posts")
@requires_auth
@validate
async def create_post(
    request,
    title: str = Field(min_length=5, max_length=200),
    content: str = Field(min_length=10),
):
    """Create new post (requires auth)."""
    post = Post(
        title=title,
        content=content,
        author_id=request.user.id
    )
    await post.save()
    
    # Broadcast new post in real-time
    await broadcast("new_post", {
        "id": post.id,
        "title": post.title,
        "author": request.user.username
    })
    
    return {"post": post.dict()}, 201

@app.put("/api/posts/{id}")
@requires_auth
async def update_post(request, id: int, title: str = None, content: str = None):
    """Update post (requires auth)."""
    post = await Post.get(id=id)
    
    if not post:
        return {"error": "Post not found"}, 404
    
    # Check ownership
    if post.author_id != request.user.id:
        return {"error": "Not authorized"}, 403
    
    if title:
        post.title = title
    if content:
        post.content = content
    
    await post.save()
    
    # Broadcast update
    await broadcast("post_updated", {"id": post.id})
    
    return {"post": post.dict()}

@app.delete("/api/posts/{id}")
@requires_auth
async def delete_post(request, id: int):
    """Delete post (requires auth)."""
    post = await Post.get(id=id)
    
    if not post:
        return {"error": "Post not found"}, 404
    
    # Check ownership
    if post.author_id != request.user.id:
        return {"error": "Not authorized"}, 403
    
    await post.delete()
    
    # Broadcast deletion
    await broadcast("post_deleted", {"id": id})
    
    return {"message": "Post deleted"}

# WebSocket endpoint
@app.websocket("/ws")
async def websocket_endpoint(websocket):
    """WebSocket for real-time updates."""
    await websocket.accept()
    
    client_id = f"client_{id(websocket)}"
    conn = realtime.add_connection(client_id, websocket)
    
    try:
        while True:
            data = await conn.receive_json()
            # Echo back
            await conn.send_json({
                "event": "echo",
                "data": data
            })
    except:
        pass
    finally:
        realtime.remove_connection(client_id)

# Stats endpoint
@app.get("/api/stats")
@requires_auth
async def get_stats(request):
    """Get app statistics (admin only)."""
    return {
        "users": await User.count(),
        "posts": await Post.count(),
        "comments": await Comment.count(),
        "realtime": realtime.get_stats(),
    }


if __name__ == "__main__":
    print("""
╔══════════════════════════════════════════════════════════╗
║                                                          ║
║  🌐 OMNIWEB - Complete Application Example              ║
║                                                          ║
║  One Framework, Every Platform                          ║
║                                                          ║
╚══════════════════════════════════════════════════════════╝

✅ Features Enabled:
   🔐 Authentication (JWT + OAuth2 + Magic Links + 2FA)
   ⚡ Real-time (WebSockets + SSE)
   📊 Admin Panel (Auto-generated CRUD)
   🗄️ ORM (DATAVOXEL)
   🔍 Validation (INTEGRIUM)
   📡 HTTP Client (VELOCRIUM)
   🖥️ Desktop Mode (Ready!)

📍 Endpoints:
   Web:       http://localhost:8000
   Admin:     http://localhost:8000/admin
   WebSocket: ws://localhost:8000/ws
   
   Auth:
     POST /auth/register
     POST /auth/login
     GET  /auth/me
   
   API:
     GET    /api/posts
     GET    /api/posts/{id}
     POST   /api/posts (auth required)
     PUT    /api/posts/{id} (auth required)
     DELETE /api/posts/{id} (auth required)

🎮 Mode:
    """)
    
    # Check if running in desktop mode
    if "--desktop" in sys.argv:
        print("   🖥️  Desktop Mode")
        print("\nStarting desktop application...\n")
        run_as_desktop(
            app,
            title="OMNIWEB Complete App",
            width=1400,
            height=900
        )
    else:
        print("   🌐 Web Mode (use --desktop for desktop mode)")
        print("\nStarting web server...\n")
        app.run(host="127.0.0.1", port=8000, reload=True)
