"""Application entrypoint for DSCons."""

from __future__ import annotations

import logging
from contextlib import asynccontextmanager

from fastapi import FastAPI

from app.core.logging_config import configure_logging
from app.core.settings import get_settings

# Cấu hình logging NGAY khi import module (trước lifespan): uvicorn --reload sinh tiến trình mới
# và import lại app.main, nên mỗi tiến trình đều có handler console -> INFO hiện trong docker logs.
configure_logging()

logger = logging.getLogger("dscons.app")


@asynccontextmanager
async def lifespan(app: FastAPI):
    """Warm up lightweight application dependencies and emit startup logs."""
    settings = get_settings()
    logger.info(
        "Starting %s v%s in %s mode on %s:%s",
        settings.app_name,
        settings.app_version,
        settings.app_env,
        settings.dscons_host,
        settings.dscons_port,
    )
    app.state.settings = settings

    import asyncio
    
    tasks = []
    
    from app.modules.core.application.antigravity_daemon_service import start_antigravity_daemon_loop
    tasks.append(asyncio.create_task(start_antigravity_daemon_loop()))
    
    from app.modules.agents.application.autonomous_engine_service import start_autonomous_scheduler_loop
    tasks.append(asyncio.create_task(start_autonomous_scheduler_loop()))
    
    from app.modules.integrations.application.cloudflared_manager import (
        get_cloudflared_manager,
        start_cloudflared_monitor_loop,
    )
    tasks.append(asyncio.create_task(start_cloudflared_monitor_loop()))
    
    from app.modules.core.application.crm_ai_cron import start_crm_ai_cron_loop
    tasks.append(asyncio.create_task(start_crm_ai_cron_loop()))
    
    from app.modules.invoices.application.invoice_processing.auto_sync_scheduler import start_invoice_auto_sync_scheduler_loop
    try:
        tasks.append(asyncio.create_task(start_invoice_auto_sync_scheduler_loop()))
    except Exception:
        pass
        
    from app.modules.core.application.lmstudio_manager import start_lmstudio_monitor_loop
    tasks.append(asyncio.create_task(start_lmstudio_monitor_loop()))

    from app.modules.core.application.openrouter_cron import start_openrouter_cron_loop
    tasks.append(asyncio.create_task(start_openrouter_cron_loop()))

    from app.core.module_framework.outbox_worker import start_outbox_worker_loop
    tasks.append(asyncio.create_task(start_outbox_worker_loop()))
    
    # --- ĐĂNG KÝ EVENT SUBSCRIBERS CHO CÁC MODULE ---
    from app.core.postgres.base_pkg.base_client import BasePostgresClient
    db_client = BasePostgresClient()
    
    try:
        from app.modules.financial.application.subscribers.project_subscribers import setup_project_subscribers
        setup_project_subscribers(db_client)
        
        from app.modules.invoices.application.subscribers.banking_subscribers import setup_invoices_subscribers
        setup_invoices_subscribers(db_client)
        
        from app.modules.inventory.application.subscribers.takeoff_subscribers import setup_inventory_subscribers
        setup_inventory_subscribers(db_client)
        
        from app.modules.takeoff.application.subscribers.inventory_subscribers import setup_takeoff_subscribers
        setup_takeoff_subscribers(db_client)
        
        from app.modules.banking.application.subscribers.invoices_subscribers import setup_banking_subscribers
        setup_banking_subscribers(db_client)
        
        from app.modules.partners.application.subscribers.invoices_subscribers import setup_partners_subscribers
        setup_partners_subscribers(db_client)
        
        logger.info("Đã đăng ký thành công tất cả Event Subscribers cho kiến trúc Modular Monolith")
    except ImportError as e:
        logger.warning(f"Chưa thể đăng ký Subscribers (Có thể do đang migrate dần): {e}")

    yield

    for t in tasks:
        t.cancel()
    
    for t in tasks:
        try:
            await t
        except asyncio.CancelledError:
            pass

    try:
        await get_cloudflared_manager().stop()
    except Exception:
        pass

    logger.info("Shutting down %s", settings.app_name)


def create_app() -> FastAPI:
    """Create and configure the FastAPI application."""

    settings = get_settings()
    app = FastAPI(
        title=settings.app_name,
        version=settings.app_version,
        docs_url=None,
        redoc_url=None,
        openapi_url=None,
        lifespan=lifespan,
    )
    
    

    # Core Module Framework: Auto-discover Mega-Modules
    from app.core.module_framework.registry import registry
    registry.discover_and_register(app)

    from pathlib import Path
    from fastapi.staticfiles import StaticFiles
    from app.api.middleware.security_middleware import EnterpriseSecurityMiddleware, SimpleGlobalRateLimitMiddleware, LegacyRedirectMiddleware

    # Add Enterprise Security, WAF inspection & OWASP Headers
    app.add_middleware(EnterpriseSecurityMiddleware)
    app.add_middleware(SimpleGlobalRateLimitMiddleware, max_requests=60, window_seconds=60)
    app.add_middleware(LegacyRedirectMiddleware)

    from fastapi import Depends
    from fastapi.openapi.docs import get_redoc_html, get_swagger_ui_html

    try:
        from app.modules.auth.presentation.auth import get_current_user
    except ImportError:
        def get_current_user(): return None

    @app.get("/docs", include_in_schema=False)
    async def get_swagger_documentation(current_user: dict = Depends(get_current_user)):
        return get_swagger_ui_html(
            openapi_url="/openapi.json",
            title=f"{settings.app_name} - OpenAPI Documentation",
            swagger_favicon_url="/static/favicon.svg",
        )

    @app.get("/redoc", include_in_schema=False)
    async def get_redoc_documentation(current_user: dict = Depends(get_current_user)):
        return get_redoc_html(
            openapi_url="/openapi.json",
            title=f"{settings.app_name} - ReDoc Documentation",
            redoc_favicon_url="/static/favicon.svg",
        )

    @app.get("/openapi.json", include_in_schema=False)
    async def get_openapi_schema(current_user: dict = Depends(get_current_user)):
        return app.openapi()

    static_dir = Path(__file__).resolve().parent / "static"
    app.mount("/static", StaticFiles(directory=str(static_dir)), name="static")

    # Secure storage router
    from app.api.storage_routes import router as storage_router
    app.include_router(storage_router)

    return app

app = create_app()
# touch
