import logging
from typing import Annotated

from fastapi import Depends, HTTPException, Request
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from sqlalchemy.ext.asyncio import AsyncSession

from gps_denied.config import get_settings
from gps_denied.core.processor import FlightProcessor
from gps_denied.core.sse import SSEEventStreamer
from gps_denied.db.engine import get_session
from gps_denied.db.repository import FlightRepository

logger = logging.getLogger(__name__)

# Singleton instance of SSE Event Streamer
_sse_streamer = SSEEventStreamer()

# Singleton FlightProcessor (one per process, reused across requests)
_processor: FlightProcessor | None = None

# JWT Bearer scheme (auto_error=False — ми самі обробляємо помилки)
_bearer = HTTPBearer(auto_error=False)


async def verify_token(
    credentials: HTTPAuthorizationCredentials | None = Depends(_bearer),
) -> None:
    """JWT перевірка. При AUTH_ENABLED=false — пропускає все."""
    settings = get_settings()
    if not settings.auth.enabled:
        return  # dev/SITL: автентифікація вимкнена

    if credentials is None:
        raise HTTPException(status_code=401, detail="Authorization header required")

    try:
        import jwt

        jwt.decode(
            credentials.credentials,
            settings.auth.secret_key,
            algorithms=[settings.auth.algorithm],
        )
    except ImportError:
        logger.warning("PyJWT not installed — JWT validation skipped")
    except Exception as exc:
        raise HTTPException(status_code=401, detail=f"Invalid token: {exc}") from exc


def get_sse_streamer() -> SSEEventStreamer:
    return _sse_streamer


async def get_repository(
    session: AsyncSession = Depends(get_session),
) -> FlightRepository:
    return FlightRepository(session)


async def get_flight_processor(
    request: Request,
    repo: FlightRepository = Depends(get_repository),
    sse: SSEEventStreamer = Depends(get_sse_streamer),
) -> FlightProcessor:
    global _processor
    if _processor is None:
        eskf_config = getattr(request.app.state, "eskf_config", None)
        _processor = FlightProcessor(repo, sse, eskf_config=eskf_config)
        # Підключаємо pipeline компоненти з lifespan
        components = getattr(request.app.state, "pipeline_components", None)
        if components:
            _processor.attach_components(**components)
    # Оновлюємо repo (нова сесія на кожен запит)
    _processor.repository = repo
    return _processor


# Аліаси для зручності в роутерах
SessionDep = Annotated[AsyncSession, Depends(get_session)]
RepoDep = Annotated[FlightRepository, Depends(get_repository)]
ProcessorDep = Annotated[FlightProcessor, Depends(get_flight_processor)]
AuthDep = Annotated[None, Depends(verify_token)]
