from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import RedirectResponse
from event_clusters import RouterCluster, EventCluster
from config import api_config
from open_api_creator import create_openapi_schema
from create_route import RouteRegisterController

from api_middlewares.token_middleware import token_middleware
from endpoints.routes import get_routes
import events


cluster_is_set = False


def create_app():
    
    def create_events_if_any_cluster_set():

        global cluster_is_set
        if not events.__all__ or cluster_is_set:
            return

        router_cluster_stack: list[RouterCluster] = [getattr(events, e, None) for e in events.__all__]
        for router_cluster in router_cluster_stack:
            event_cluster_stack: list[EventCluster] = list(router_cluster.event_clusters.values())
            for event_cluster in event_cluster_stack:
                try:
                    event_cluster.set_events_to_database()
                except Exception as e:
                    print(f"Error creating event cluster: {e}")

        cluster_is_set = True

    application = FastAPI(**api_config.api_info)
    application.add_middleware(
        CORSMiddleware,
        allow_origins=api_config.ALLOW_ORIGINS,
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )

    @application.middleware("http")
    async def add_token_middleware(request: Request, call_next):
        return await token_middleware(request, call_next)

    @application.get("/", description="Redirect Route", include_in_schema=False)
    async def redirect_to_docs():
        return RedirectResponse(url="/docs")

    route_register = RouteRegisterController(app=application, router_list=get_routes())
    application = route_register.register_routes()

    create_events_if_any_cluster_set()
    application.openapi = lambda _=application: create_openapi_schema(_)
    return application
