from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from config import settings

from simulator import alarm_simulator, ticket_simulator, cleanup_alarms, cleanup_incidents, robot_simulator

import asyncio
from contextlib import asynccontextmanager

import time

from .incidents import router as incidents_router
from .alarms import router as alarms_router
from .cellsites import router as cellsites_router
from .simulator import router as simulator_router
from .robots import router as robots_router
from .gqlapi import graphql_app as test_graphql

origins: list[str] = settings.cors_origins.split(",")

ALARM_CLEANUP_INTERVAL = 180
INCIDENT_CLEANUP_INTERVAL = 240

# NOTE: All 5 simulators run on a single thread using Python's event loop. Using this instead of multithreading to keep things simple. Good enough for demoing the idea.
@asynccontextmanager
async def lifespan(app: FastAPI):
    task1 = asyncio.create_task(alarm_simulator(5))
    task2 = asyncio.create_task(ticket_simulator(20))
    task3 = asyncio.create_task(cleanup_alarms(interval=ALARM_CLEANUP_INTERVAL, max_age_seconds=5))
    task4 = asyncio.create_task(cleanup_incidents(interval=INCIDENT_CLEANUP_INTERVAL, max_age_seconds=10))
    task5 = asyncio.create_task(robot_simulator(8))

    # NOTE: This is for the stats endpoint, to send to frontend
    simulator.next_alarm_cleanup_at = time.time() + ALARM_CLEANUP_INTERVAL
    simulator.next_incident_cleanup_at = time.time() + INCIDENT_CLEANUP_INTERVAL

    yield
    task1.cancel()
    task2.cancel()
    task3.cancel()
    task4.cancel()
    task5.cancel()

def create_app() -> FastAPI:
    # TODO: Add a toggle / Flag or endpoint to turn off the simulator
    # app = FastAPI()
    app = FastAPI(lifespan=lifespan)

    app.add_middleware(
        CORSMiddleware,
        allow_origins=origins,
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )

    app.include_router(incidents_router, prefix="/api/v1")
    app.include_router(cellsites_router, prefix="/api/v1")
    app.include_router(alarms_router, prefix="/api/v1")
    app.include_router(simulator_router, prefix="/api/v1")
    app.include_router(robots_router, prefix="/api/v1")
    # Graphql test
    app.include_router(test_graphql, prefix="/graphql")

    return app
