"""FastAPI web application for workflow orchestration UI."""

from contextlib import asynccontextmanager
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from pathlib import Path
import ombra
from ..discovery import discover_workflows_in_directory
from .endpoints import create_workflow_endpoints


@asynccontextmanager
async def lifespan(app: FastAPI):
    """Lifecycle management for the application."""
    # Suppress uvicorn access logs for polling endpoints
    import logging
    
    class EndpointFilter(logging.Filter):
        def filter(self, record: logging.LogRecord) -> bool:
            return record.getMessage().find("GET /api/executions") == -1

    try:
        logging.getLogger("uvicorn.access").addFilter(EndpointFilter())
    except Exception:
        pass

    # Startup: Discover workflows
    print("\n" + "=" * 60)
    print("🚀 Starting ombra Workflow Orchestration")
    print("=" * 60)

    project_root = Path.cwd()
    print(f"📁 Project root: {project_root}")

    search_paths = [
        project_root / "workflows",
        project_root / "src" / "workflows",
    ]

    total_imported = 0
    for path in search_paths:
        if path.exists():
            print(f"🔍 Scanning: {path}")
            try:
                imported = discover_workflows_in_directory(path)
                if imported:
                    print(f"   ✅ Imported {len(imported)} files")
                    for file in imported:
                        print(f"      - {Path(file).name}")
                    total_imported += len(imported)
                else:
                    print(f"   ⚠️  No Python files found")
            except Exception as e:
                print(f"   ❌ Error scanning: {e}")
        else:
            print(f"⏭️  Skipping (not found): {path}")

    workflows = ombra.get_all_workflows()
    print(f"\n📦 Registered {len(workflows)} workflow(s)")
    for wf in workflows:
        print(f"   - {wf.name}: {len(wf._steps)} steps")

    # Cleanup old workflow schemas that no longer have code
    from ombra.execution import get_execution_manager
    exec_manager = get_execution_manager()

    active_workflow_names = {wf.name for wf in workflows}
    db_schemas = exec_manager.db.load_workflow_schemas()
    db_workflow_names = {schema['workflow_name'] for schema in db_schemas}

    # Find workflows in DB that are not in code
    orphaned_workflows = db_workflow_names - active_workflow_names

    if orphaned_workflows:
        print(f"\n🧹 Cleaning up {len(orphaned_workflows)} old workflow(s):")
        for workflow_name in orphaned_workflows:
            print(f"   - Removing: {workflow_name}")
            exec_manager.db.delete_workflow_schema(workflow_name)
        print(f"✅ Cleanup complete")

    # Register dynamic API endpoints from workflow schemas
    # Schemas are loaded from database and persisted across reloads
    print(f"\n🔌 Registering API endpoints from schemas...")
    create_workflow_endpoints(app)
    print(f"✅ Dynamic endpoints registered (with input validation, survive code reloads)")

    if not workflows:
        print("\n💡 Tip: Create a workflow in workflows/ or src/workflows/ directory")

    print(f"📖 View docs at: http://localhost:8000/docs")

    print("=" * 60 + "\n")

    yield

    # Shutdown
    print("👋 Shutting down...")


# Get the web directory path
WEB_DIR = Path(__file__).parent
TEMPLATES_DIR = WEB_DIR / "templates"
STATIC_DIR = WEB_DIR / "static"

# Create FastAPI app with lifespan
app = FastAPI(
    lifespan=lifespan,
    openapi_tags=[
        {
            "name": "Workflows",
            "description": "Execute registered workflows with automatic checkpointing"
        },
        {
            "name": "Internal",
            "description": "Internal APIs for workflow management and monitoring"
        }
    ]
)

# Setup Jinja2 templates
templates = Jinja2Templates(directory=str(TEMPLATES_DIR))

# Mount static files (CSS, JS)
if STATIC_DIR.exists():
    app.mount("/static", StaticFiles(directory=str(STATIC_DIR)), name="static")


@app.get("/", response_class=HTMLResponse, include_in_schema=False)
async def home(request: Request):
    """Home page - redirect to workflows."""
    from fastapi.responses import RedirectResponse
    return RedirectResponse(url="/workflows", status_code=302)


@app.get("/workflows", response_class=HTMLResponse, include_in_schema=False)
async def workflows_page(request: Request):
    """Workflows page - list recent executions."""
    from ombra.execution import get_execution_manager

    execution_manager = get_execution_manager()

    # Get recent executions (last 100)
    all_executions = execution_manager.get_all_executions()
    recent_executions = sorted(
        all_executions,
        key=lambda e: e.started_at or e.completed_at or "",
        reverse=True
    )[:100]

    executions_data = [
        {
            "execution_id": ex.execution_id,
            "workflow_name": ex.workflow_name,
            "status": ex.status.value,
            "started_at": ex.started_at.strftime("%Y-%m-%d %H:%M:%S") if ex.started_at else None,
            "completed_at": ex.completed_at.strftime("%Y-%m-%d %H:%M:%S") if ex.completed_at else None,
            "num_steps": len(ex.step_executions),
            "error": ex.error
        }
        for ex in recent_executions
    ]

    return templates.TemplateResponse(
        "workflows.html",
        {
            "request": request,
            "executions": executions_data
        }
    )


@app.get("/executions/{execution_id}", response_class=HTMLResponse, include_in_schema=False)
async def execution_detail(request: Request, execution_id: str):
    """Execution detail page - show full details of a specific execution."""
    from ombra.execution import get_execution_manager
    from fastapi import HTTPException

    execution_manager = get_execution_manager()
    execution = execution_manager.get_execution(execution_id)

    if not execution:
        raise HTTPException(status_code=404, detail=f"Execution {execution_id} not found")

    # Convert execution to dict for template
    execution_data = {
        "execution_id": execution.execution_id,
        "workflow_name": execution.workflow_name,
        "status": execution.status.value,
        "started_at": execution.started_at.strftime("%Y-%m-%d %H:%M:%S") if execution.started_at else None,
        "completed_at": execution.completed_at.strftime("%Y-%m-%d %H:%M:%S") if execution.completed_at else None,
        "error": execution.error,
        "inputs": execution.inputs,
        "outputs": execution.outputs,
        "step_executions": execution.step_executions,
        "num_checkpoints": len(execution.checkpoints)
    }

    return templates.TemplateResponse(
        "execution_detail.html",
        {
            "request": request,
            "execution": execution_data
        }
    )


@app.get("/api/executions/{execution_id}", tags=["Internal"])
async def get_execution_json(execution_id: str):
    """Get execution details as JSON (API endpoint)."""
    from ombra.execution import get_execution_manager
    from fastapi import HTTPException

    execution_manager = get_execution_manager()
    execution = execution_manager.get_execution(execution_id)

    if not execution:
        raise HTTPException(status_code=404, detail="Execution not found")

    return execution.to_dict()


@app.get("/api/executions", tags=["Internal"])
async def get_executions_list(limit: int = 100):
    """Get list of recent executions."""
    from ombra.execution import get_execution_manager

    execution_manager = get_execution_manager()

    # Get recent executions (last N)
    all_executions = execution_manager.get_all_executions()
    recent_executions = sorted(
        all_executions,
        key=lambda e: e.started_at or e.completed_at or "",
        reverse=True
    )[:limit]

    executions_data = [
        {
            "execution_id": ex.execution_id,
            "workflow_name": ex.workflow_name,
            "status": ex.status.value,
            "started_at": ex.started_at.strftime("%Y-%m-%d %H:%M:%S") if ex.started_at else None,
            "completed_at": ex.completed_at.strftime("%Y-%m-%d %H:%M:%S") if ex.completed_at else None,
            "num_steps": len(ex.step_executions),
            "error": ex.error
        }
        for ex in recent_executions
    ]

    return executions_data


@app.get("/health", tags=["Internal"])
async def health():
    """Health check endpoint."""
    return {"status": "healthy"}


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