"""
Cube Agent API

FastAPI application that exposes the Cube Agent via REST API with streaming support.
"""

import json
from typing import Optional
from fastapi import FastAPI, HTTPException
from fastapi.responses import StreamingResponse
from fastapi.middleware.cors import CORSMiddleware
import asyncio

from .models import (
    ChatRequest,
    StreamEvent,
    SessionInfo,
    HealthResponse,
    EventType
)
from .agent import (
    run_agent_streaming,
    check_tool_status,
    check_apollo_credentials,
    get_model_name
)
from .sessions import (
    get_or_create_session,
    get_session,
    list_sessions,
    delete_session,
    SESSIONS_DIR
)

app = FastAPI(
    title="Cube Agent API",
    description="API for EdgescaleAI Cube operations and Helm deployments",
    version="1.0.0"
)

# CORS for frontend access
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


@app.get("/health", response_model=HealthResponse)
async def health_check():
    """Check agent health and tool availability."""
    return HealthResponse(
        status="healthy",
        tools=check_tool_status(),
        apollo_configured=check_apollo_credentials(),
        model=get_model_name()
    )


@app.post("/chat")
async def chat(request: ChatRequest):
    """
    Send a message to the agent and receive streaming response.

    Returns Server-Sent Events (SSE) stream with:
    - thinking: Agent's reasoning process
    - tool_call: Tools being invoked
    - tool_result: Results from tools
    - text: Final response text
    - done: Agent finished
    - error: Error occurred
    """
    session = get_or_create_session(request.session_id)

    async def event_generator():
        async for event in run_agent_streaming(request.message, session):
            yield f"data: {event.model_dump_json()}\n\n"

    return StreamingResponse(
        event_generator(),
        media_type="text/event-stream",
        headers={
            "Cache-Control": "no-cache",
            "Connection": "keep-alive",
            "X-Session-ID": session.session_id
        }
    )


@app.post("/chat/sync")
async def chat_sync(request: ChatRequest):
    """
    Send a message and wait for complete response (non-streaming).

    Returns the full response with all events collected.
    """
    session = get_or_create_session(request.session_id)

    events = []
    final_text = ""
    error = None

    async for event in run_agent_streaming(request.message, session):
        events.append(event.model_dump())
        if event.event == EventType.TEXT:
            final_text = event.data.get("content", "")
        elif event.event == EventType.ERROR:
            error = event.data.get("message", "Unknown error")

    if error:
        raise HTTPException(status_code=500, detail=error)

    return {
        "session_id": session.session_id,
        "response": final_text,
        "events": events
    }


@app.get("/sessions")
async def get_sessions():
    """List all active sessions."""
    sessions = list_sessions()
    return [
        SessionInfo(
            session_id=s.session_id,
            message_count=len(s.messages),
            created_at=s.created_at,
            last_active=s.last_active
        )
        for s in sessions
    ]


@app.get("/sessions/{session_id}")
async def get_session_info(session_id: str):
    """Get information about a specific session."""
    session = get_session(session_id)
    if not session:
        raise HTTPException(status_code=404, detail="Session not found")

    return {
        "session_id": session.session_id,
        "message_count": len(session.messages),
        "created_at": session.created_at,
        "last_active": session.last_active,
        "messages": session.messages
    }


@app.delete("/sessions/{session_id}")
async def delete_session_endpoint(session_id: str):
    """Delete a session."""
    if delete_session(session_id):
        return {"status": "deleted"}
    raise HTTPException(status_code=404, detail="Session not found")


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