"""FastAPI application entry point with lifespan management."""
# ruff: noqa: E402
# ---------------------------------------------------------------------------
# SSL + proxy injection — MUST happen before any HTTP client imports
# ---------------------------------------------------------------------------
import os as _os
import ssl as _ssl
from pathlib import Path as _Path

_COMBINED_CERT = _Path(__file__).resolve().parent.parent / "combined-ca-bundle.pem"

if _COMBINED_CERT.exists():
    _cert_path = str(_COMBINED_CERT)
    # Env vars for libraries that respect them (requests, urllib3)
    _os.environ["SSL_CERT_FILE"] = _cert_path
    _os.environ["REQUESTS_CA_BUNDLE"] = _cert_path
    _os.environ["CURL_CA_BUNDLE"] = _cert_path

    # Monkey-patch ssl.create_default_context so that ALL libraries
    # (aiohttp, httpx, google-genai, alpaca-py, etc.) automatically
    # use our combined CA bundle that includes the corporate root cert.
    _original_create_default_context = _ssl.create_default_context

    def _patched_create_default_context(
        purpose=_ssl.Purpose.SERVER_AUTH, *, cafile=None, capath=None, cadata=None
    ):
        ctx = _original_create_default_context(
            purpose, cafile=cafile, capath=capath, cadata=cadata
        )
        # Always load our combined bundle on top of whatever was loaded
        ctx.load_verify_locations(cafile=_cert_path)
        return ctx

    _ssl.create_default_context = _patched_create_default_context

    # Also patch aiohttp's cached SSL context objects directly, since
    # aiohttp creates them at import time and may have already cached
    # a context without our corporate CA bundle.
    try:
        import aiohttp.connector as _aio_conn
        if hasattr(_aio_conn, '_SSL_CONTEXT_VERIFIED') and _aio_conn._SSL_CONTEXT_VERIFIED is not None:
            _aio_conn._SSL_CONTEXT_VERIFIED.load_verify_locations(cafile=_cert_path)
        if hasattr(_aio_conn, '_SSL_CONTEXT_UNVERIFIED') and _aio_conn._SSL_CONTEXT_UNVERIFIED is not None:
            _aio_conn._SSL_CONTEXT_UNVERIFIED.load_verify_locations(cafile=_cert_path)
    except ImportError:
        pass

# Corporate proxy — needed when Kiro spawns the process (no .zshrc sourced)
# Only enable this if explicitly requested via environment variable.
if _os.environ.get("USE_CORP_PROXY", "0") == "1":
    _PROXY = "http://aproxy.corproot.net:8080"
    _NO_PROXY = "corproot.net,sharedtcs.net,127.0.0.1,localhost,bix.swisscom.com,swisscom.com"
    _os.environ.setdefault("HTTP_PROXY", _PROXY)
    _os.environ.setdefault("HTTPS_PROXY", _PROXY)
    _os.environ.setdefault("NO_PROXY", _NO_PROXY)

import logging
import sys
from contextlib import asynccontextmanager
from collections.abc import AsyncGenerator

from fastapi import FastAPI
from passlib.hash import bcrypt
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.config import settings
from app.database import async_session_factory, engine
from app.middleware import register_exception_handlers
from app.models.user import User
from app.scheduler import configure_scheduler, load_schedule_config, scheduler
from app.routers.admin import router as admin_router
from app.routers.auth import router as auth_router
from app.routers.health import router as health_router
from app.routers.ingestion import router as ingestion_router
from app.routers.ohlcv import router as ohlcv_router
from app.routers.indicators import router as indicators_router
from app.routers.fundamentals import router as fundamentals_router
from app.routers.scores import router as scores_router
from app.routers.trades import router as trades_router
from app.routers.watchlist import router as watchlist_router
from app.routers.sentiment import router as sentiment_router
from app.routers.sr_levels import router as sr_levels_router
from app.routers.tickers import router as tickers_router
from app.routers.jobs import router as jobs_router
from app.routers.market import router as market_router
from app.routers.paper_trades import router as paper_trades_router


def _configure_logging() -> None:
    """Set up structured JSON-style logging."""
    handler = logging.StreamHandler(sys.stdout)
    handler.setFormatter(
        logging.Formatter(
            '{"time":"%(asctime)s","level":"%(levelname)s",'
            '"logger":"%(name)s","message":"%(message)s"}'
        )
    )
    root = logging.getLogger()
    root.handlers.clear()
    root.addHandler(handler)
    root.setLevel(settings.log_level.upper())


async def _create_default_admin(session: AsyncSession) -> None:
    """Create the default admin account if no admin user exists."""
    result = await session.execute(
        select(User).where(User.role == "admin")
    )
    if result.scalar_one_or_none() is None:
        admin = User(
            username="admin",
            password_hash=bcrypt.hash("admin"),
            role="admin",
            has_access=True,
        )
        session.add(admin)
        await session.commit()
        logging.getLogger(__name__).info("Default admin account created")


@asynccontextmanager
async def lifespan(_app: FastAPI) -> AsyncGenerator[None, None]:
    """Manage startup and shutdown lifecycle."""
    logger = logging.getLogger(__name__)
    _configure_logging()
    logger.info("Starting Stock Data Backend")

    async with async_session_factory() as session:
        await _create_default_admin(session)
        schedule_config = await load_schedule_config(session)

    configure_scheduler(schedule_config)
    scheduler.start()
    logger.info("Scheduler started")

    yield

    scheduler.shutdown(wait=False)
    logger.info("Scheduler stopped")
    await engine.dispose()
    logger.info("Shutting down")


app = FastAPI(
    title="Stock Data Backend",
    version="0.1.0",
    lifespan=lifespan,
)

register_exception_handlers(app)
app.include_router(health_router, prefix="/api/v1")
app.include_router(auth_router, prefix="/api/v1")
app.include_router(admin_router, prefix="/api/v1")
app.include_router(tickers_router, prefix="/api/v1")
app.include_router(ohlcv_router, prefix="/api/v1")
app.include_router(ingestion_router, prefix="/api/v1")
app.include_router(indicators_router, prefix="/api/v1")
app.include_router(sr_levels_router, prefix="/api/v1")
app.include_router(sentiment_router, prefix="/api/v1")
app.include_router(fundamentals_router, prefix="/api/v1")
app.include_router(scores_router, prefix="/api/v1")
app.include_router(trades_router, prefix="/api/v1")
app.include_router(watchlist_router, prefix="/api/v1")
app.include_router(jobs_router, prefix="/api/v1")
app.include_router(market_router, prefix="/api/v1")
app.include_router(paper_trades_router, prefix="/api/v1")
