#!/usr/bin/env python3
"""Orchestration Dashboard Server - Serves projects and provides API"""

from fastapi import FastAPI, HTTPException
from fastapi.responses import HTMLResponse, FileResponse
from fastapi.staticfiles import StaticFiles
from pathlib import Path
import json
from datetime import datetime
from typing import List, Dict, Optional
import os

app = FastAPI(title="Orchestration Dashboard")

# Base paths
BASE_DIR = Path("/home/jooyoung/.openclaw/workspace-260312/orchestration")
PROJECTS_DIR = BASE_DIR / "projects"
REGISTRY_FILE = BASE_DIR / "registry.json"

# Ensure directories exist
PROJECTS_DIR.mkdir(parents=True, exist_ok=True)


def load_registry() -> List[Dict]:
    """Load project registry from file"""
    if not REGISTRY_FILE.exists():
        return []
    try:
        with open(REGISTRY_FILE, 'r', encoding='utf-8') as f:
            return json.load(f)
    except Exception:
        return []


def save_registry(registry: List[Dict]):
    """Save project registry to file"""
    with open(REGISTRY_FILE, 'w', encoding='utf-8') as f:
        json.dump(registry, f, indent=2, ensure_ascii=False)


def scan_projects() -> List[Dict]:
    """Auto-detect projects in projects/ directory"""
    projects = []
    if not PROJECTS_DIR.exists():
        return projects
    
    for project_dir in PROJECTS_DIR.iterdir():
        if project_dir.is_dir():
            # Check if it has an index.html
            index_file = project_dir / "index.html"
            has_game = index_file.exists()
            
            # Get metadata if exists
            meta_file = project_dir / "metadata.json"
            metadata = {}
            if meta_file.exists():
                try:
                    with open(meta_file, 'r', encoding='utf-8') as f:
                        metadata = json.load(f)
                except Exception:
                    pass
            
            projects.append({
                "name": project_dir.name,
                "path": str(project_dir),
                "has_game": has_game,
                "created": metadata.get("created", "unknown"),
                "description": metadata.get("description", ""),
                "status": "ready" if has_game else "empty"
            })
    
    return projects


@app.get("/", response_class=HTMLResponse)
async def dashboard():
    """Main orchestration dashboard"""
    projects = scan_projects()
    
    # Generate project cards HTML
    cards_html = ""
    for project in projects:
        status_badge = "✅" if project["has_game"] else "⚠️"
        play_link = f'<a href="/p/{project["name"]}/" class="btn">Play</a>' if project["has_game"] else '<span class="btn disabled">No Game</span>'
        
        cards_html += f'''
        <div class="card">
            <h3>{status_badge} {project["name"]}</h3>
            <p class="desc">{project["description"] or "No description"}</p>
            <div class="meta">
                <span>Status: {project["status"]}</span>
                <span>Created: {project["created"]}</span>
            </div>
            <div class="actions">
                {play_link}
                <a href="/api/projects/{project["name"]}/status" class="btn">API</a>
            </div>
        </div>
        '''
    
    if not cards_html:
        cards_html = '<p class="empty">No projects yet. Create one using the orchestration system!</p>'
    
    html = f'''<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Orchestration Dashboard</title>
    <style>
        * {{ margin: 0; padding: 0; box-sizing: border-box; }}
        body {{
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            padding: 2rem;
        }}
        .container {{
            max-width: 1200px;
            margin: 0 auto;
        }}
        header {{
            background: white;
            border-radius: 1rem;
            padding: 2rem;
            margin-bottom: 2rem;
            box-shadow: 0 4px 6px rgba(0,0,0,0.1);
        }}
        h1 {{
            color: #667eea;
            font-size: 2.5rem;
            margin-bottom: 0.5rem;
        }}
        .subtitle {{
            color: #666;
            font-size: 1.1rem;
        }}
        .grid {{
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
            gap: 1.5rem;
        }}
        .card {{
            background: white;
            border-radius: 1rem;
            padding: 1.5rem;
            box-shadow: 0 4px 6px rgba(0,0,0,0.1);
            transition: transform 0.2s, box-shadow 0.2s;
        }}
        .card:hover {{
            transform: translateY(-5px);
            box-shadow: 0 8px 12px rgba(0,0,0,0.15);
        }}
        .card h3 {{
            color: #333;
            margin-bottom: 0.5rem;
            font-size: 1.3rem;
        }}
        .desc {{
            color: #666;
            margin-bottom: 1rem;
            line-height: 1.5;
        }}
        .meta {{
            display: flex;
            gap: 1rem;
            margin-bottom: 1rem;
            font-size: 0.9rem;
            color: #888;
        }}
        .actions {{
            display: flex;
            gap: 0.5rem;
        }}
        .btn {{
            display: inline-block;
            padding: 0.5rem 1rem;
            background: #667eea;
            color: white;
            text-decoration: none;
            border-radius: 0.5rem;
            font-size: 0.9rem;
            transition: background 0.2s;
        }}
        .btn:hover {{
            background: #5568d3;
        }}
        .btn.disabled {{
            background: #ccc;
            cursor: not-allowed;
        }}
        .empty {{
            text-align: center;
            color: white;
            font-size: 1.2rem;
            padding: 3rem;
            background: rgba(255,255,255,0.1);
            border-radius: 1rem;
        }}
        .stats {{
            display: flex;
            gap: 2rem;
            margin-top: 1rem;
        }}
        .stat {{
            background: #f0f0f0;
            padding: 1rem;
            border-radius: 0.5rem;
        }}
        .stat-value {{
            font-size: 2rem;
            font-weight: bold;
            color: #667eea;
        }}
        .stat-label {{
            color: #666;
            font-size: 0.9rem;
        }}
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>🎮 Orchestration Dashboard</h1>
            <p class="subtitle">Game Creation & Serving Platform</p>
            <div class="stats">
                <div class="stat">
                    <div class="stat-value">{len(projects)}</div>
                    <div class="stat-label">Total Projects</div>
                </div>
                <div class="stat">
                    <div class="stat-value">{sum(1 for p in projects if p["has_game"])}</div>
                    <div class="stat-label">Ready Games</div>
                </div>
            </div>
        </header>
        
        <div class="grid">
            {cards_html}
        </div>
    </div>
</body>
</html>'''
    
    return HTMLResponse(content=html)


@app.get("/api/health")
async def health():
    """Health check endpoint"""
    return {
        "status": "ok",
        "timestamp": datetime.now().isoformat(),
        "projects_count": len(scan_projects())
    }


@app.get("/api/projects")
async def get_projects():
    """Get all projects"""
    return {
        "projects": scan_projects(),
        "timestamp": datetime.now().isoformat()
    }


@app.get("/api/projects/{project_name}/status")
async def get_project_status(project_name: str):
    """Get individual project status"""
    projects = scan_projects()
    project = next((p for p in projects if p["name"] == project_name), None)
    
    if not project:
        raise HTTPException(status_code=404, detail=f"Project '{project_name}' not found")
    
    return project


# Dynamic project serving - scan both projects/ and serving/ directories
SERVING_DIR = BASE_DIR / "serving"
SERVING_DIR.mkdir(parents=True, exist_ok=True)

def _mount_project_dirs():
    """Mount all project directories for static serving"""
    for scan_dir in [PROJECTS_DIR, SERVING_DIR]:
        if not scan_dir.exists():
            continue
        for project_dir in scan_dir.iterdir():
            # Resolve symlinks
            real_dir = project_dir.resolve() if project_dir.is_symlink() else project_dir
            if real_dir.is_dir() and (real_dir / "index.html").exists():
                route = f"/p/{project_dir.name}"
                try:
                    app.mount(route, StaticFiles(directory=str(real_dir), html=True), name=f"serve_{project_dir.name}")
                except Exception:
                    pass

_mount_project_dirs()


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8600)
