"""Risk Engine API - FastAPI application for order risk evaluation and approval workflow."""
from __future__ import annotations

from contextlib import asynccontextmanager

import asyncpg
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

from services.risk.approval import (
    expire_stale_approvals,
    get_approval_by_id,
    get_pending_approvals,
    review_approval,
)
from services.risk.engine import (
    AccountRiskState,
    PortfolioRiskConfig,
    ProposedOrder,
    RiskEvaluation,
    evaluate_order,
)
from services.shared.config import load_config
from services.shared.logging import setup_logging

config = load_config()
pool: asyncpg.Pool | None = None


@asynccontextmanager
async def lifespan(app: FastAPI):
    global pool
    setup_logging("risk_engine", level=config.log_level, json_output=config.json_logs)
    pool = await asyncpg.create_pool(dsn=config.postgres.dsn, min_size=2, max_size=8)
    yield
    if pool:
        await pool.close()


app = FastAPI(title="Stonks Oracle - Risk Engine", lifespan=lifespan)


class EvaluateRequest(BaseModel):
    order: ProposedOrder
    config: PortfolioRiskConfig | None = None
    state: AccountRiskState | None = None


@app.post("/evaluate", response_model=RiskEvaluation)
async def evaluate(req: EvaluateRequest) -> RiskEvaluation:
    risk_config = req.config or PortfolioRiskConfig()
    return evaluate_order(req.order, risk_config, req.state)


@app.get("/health")
async def health():
    return {"status": "ok"}


class ReviewRequest(BaseModel):
    approved: bool
    reviewed_by: str = "operator"
    review_note: str = ""


@app.get("/approvals/pending")
async def list_pending():
    if not pool:
        raise HTTPException(503, "Database not ready")
    requests = await get_pending_approvals(pool)
    return [r.to_dict() for r in requests]


@app.get("/approvals/{approval_id}")
async def get_approval(approval_id: str):
    if not pool:
        raise HTTPException(503, "Database not ready")
    req = await get_approval_by_id(pool, approval_id)
    if not req:
        raise HTTPException(404, "Approval not found")
    return req.to_dict()


@app.post("/approvals/{approval_id}/review")
async def review(approval_id: str, body: ReviewRequest):
    if not pool:
        raise HTTPException(503, "Database not ready")
    status = await review_approval(
        pool, approval_id, body.approved, body.reviewed_by, body.review_note,
    )
    if status is None:
        raise HTTPException(404, "Approval not found or no longer pending")
    return {"approval_id": approval_id, "status": status.value}


@app.post("/approvals/expire")
async def expire():
    if not pool:
        raise HTTPException(503, "Database not ready")
    expired = await expire_stale_approvals(pool)
    return {"expired": len(expired), "items": expired}
