from __future__ import annotations

import logging
from contextlib import asynccontextmanager
from pathlib import Path

from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
from starlette.concurrency import run_in_threadpool

from app.config import get_settings
from app.db import close_pool, init_pool
from app.models import SearchRequest, SearchResponse
from app.rag import answer_question
from app.vertex import init_vertex

logging.basicConfig(level=logging.INFO, format="%(levelname)s %(name)s: %(message)s")
log = logging.getLogger("partnerlogic")

STATIC_DIR = Path(__file__).resolve().parent.parent / "static"


@asynccontextmanager
async def lifespan(_app: FastAPI):
    get_settings()
    try:
        init_pool()
    except Exception:
        log.exception("PostgreSQL pool failed to start. UI will still load; /search will fail until the database is up.")
    try:
        init_vertex()
    except Exception:
        log.exception("Vertex AI failed to initialize. Set GCP_PROJECT_ID and GOOGLE_APPLICATION_CREDENTIALS.")
    yield
    close_pool()


app = FastAPI(
    title="PartnerLogic",
    description="MLT Aikins private document intelligence prototype",
    lifespan=lifespan,
)

app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:8000", "http://127.0.0.1:8000"],
    allow_methods=["GET", "POST"],
    allow_headers=["Content-Type"],
)

app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")


@app.get("/")
async def index() -> FileResponse:
    return FileResponse(STATIC_DIR / "index.html")


@app.get("/health")
async def health() -> dict[str, str]:
    return {"status": "ok", "instance": "MLT Aikins Private Instance"}


@app.post("/search", response_model=SearchResponse)
async def search(payload: SearchRequest) -> SearchResponse:
    question = payload.question.strip()
    if not question:
        raise HTTPException(status_code=400, detail="Question is required.")
    try:
        return await run_in_threadpool(answer_question, question)
    except Exception as exc:  # noqa: BLE001 — surface Vertex/DB failures cleanly in a PoC
        raise HTTPException(status_code=503, detail=str(exc)) from exc
