"""AWT Cloud — FastAPI application entry point."""

from __future__ import annotations

import logging
from collections.abc import AsyncGenerator
from contextlib import asynccontextmanager
from pathlib import Path

from fastapi import FastAPI, Request, Response
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from sqlalchemy import text

from app.config import settings
from app.database import engine
from app.models import Base
from app.routers import (
    ai_config,
    billing,
    documents,
    fix_guides,
    github,
    keys,
    scan,
    tests,
    v1,
)

logger = logging.getLogger(__name__)

# ---------------------------------------------------------------------------
# Optional: Sentry
# ---------------------------------------------------------------------------
if settings.sentry_dsn:
    try:
        import sentry_sdk  # type: ignore[import-untyped]

        sentry_sdk.init(dsn=settings.sentry_dsn, traces_sample_rate=0.1)
        logger.info("Sentry initialized")
    except ImportError:
        logger.warning("sentry-sdk not installed, skipping Sentry integration")

# ---------------------------------------------------------------------------
# Optional: structlog
# ---------------------------------------------------------------------------
try:
    import structlog  # type: ignore[import-untyped]

    structlog.configure(
        processors=[
            structlog.stdlib.filter_by_level,
            structlog.stdlib.add_logger_name,
            structlog.stdlib.add_log_level,
            structlog.stdlib.PositionalArgumentsFormatter(),
            structlog.processors.TimeStamper(fmt="iso"),
            structlog.processors.StackInfoRenderer(),
            structlog.processors.format_exc_info,
            structlog.processors.UnicodeDecoder(),
            structlog.dev.ConsoleRenderer(),
        ],
        wrapper_class=structlog.stdlib.BoundLogger,
        context_class=dict,
        logger_factory=structlog.PrintLoggerFactory(),
    )
except ImportError:
    pass


# ---------------------------------------------------------------------------
# Lifespan: DB init + background worker
# ---------------------------------------------------------------------------


@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
    """Create DB tables and start background worker on startup."""
    # Log DB backend for debugging
    db_url = settings.database_url
    if db_url.startswith("sqlite"):
        logger.warning(
            "Using SQLite — data will be lost on Render restart!"
            " Set AWT_DATABASE_URL to PostgreSQL."
        )
    else:
        logger.info("Database: %s", db_url.split("@")[-1] if "@" in db_url else "(configured)")

    # DB tables
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)

    # Column migrations — each in its own transaction
    # (PostgreSQL aborts the entire transaction on ALTER error)
    for col_sql in [
        "ALTER TABLE scans ADD COLUMN observations_json TEXT",
        "ALTER TABLE scans ADD COLUMN logs_json TEXT",
    ]:
        try:
            async with engine.begin() as conn:
                await conn.execute(text(col_sql))
                logger.info("Migration OK: %s", col_sql)
        except Exception:
            pass  # column already exists

    # Background worker
    from app.worker import worker

    await worker.start()

    yield

    # Shutdown
    await worker.stop()


app = FastAPI(
    title=settings.app_name,
    version="0.2.0",
    lifespan=lifespan,
)

# -- CORS --
_cors_origins: list[str] = (
    ["*"]
    if settings.cors_origins.strip() == "*"
    else [o.strip() for o in settings.cors_origins.split(",") if o.strip()]
)
app.add_middleware(
    CORSMiddleware,
    allow_origins=_cors_origins,
    allow_credentials=False,
    allow_methods=["*"],
    allow_headers=["*"],
)

# -- Static: screenshots --
_ss_dir = Path(settings.screenshot_dir)
_ss_dir.mkdir(parents=True, exist_ok=True)
app.mount("/screenshots", StaticFiles(directory=str(_ss_dir)), name="screenshots")

# -- Routers --
app.include_router(tests.router)
app.include_router(scan.router)
app.include_router(documents.router)
app.include_router(keys.router)
app.include_router(v1.router)
app.include_router(billing.router)
app.include_router(ai_config.router)
app.include_router(github.router)
app.include_router(fix_guides.router)


# -- Rate limit response headers --
@app.middleware("http")
async def add_rate_limit_headers(  # type: ignore[no-untyped-def]
    request: Request, call_next
) -> Response:
    """Inject X-RateLimit-* headers into responses."""
    response: Response = await call_next(request)

    if hasattr(request.state, "rate_limit"):
        limit = request.state.rate_limit
        remaining = request.state.rate_remaining
        if limit >= 0:
            response.headers["X-RateLimit-Limit"] = str(limit)
            response.headers["X-RateLimit-Remaining"] = str(remaining)

    return response


# -- Health check (simple) --
@app.get("/health")
async def health_simple() -> dict[str, str]:
    """Simple health check (load balancer / uptime monitor)."""
    return {"status": "ok"}


# -- Health check (detailed) --
@app.get("/api/health")
async def health_detailed() -> dict[str, object]:
    """Detailed health check — DB, Worker, AI provider status."""
    from app.health import get_health

    return await get_health()


# -- Worker status --
@app.get("/api/worker/status")
async def worker_status() -> dict[str, object]:
    """Worker status endpoint (no auth required)."""
    from app.worker import worker

    return {
        "running": worker.is_running,
        "active_tests": worker.active_count,
        "max_concurrent": settings.max_concurrent,
    }
