"""The client-facing quote builder.

The client tailors the proposal by toggling line items, then submits a request.
Selections upsert (one row per item, latest wins); a submitted request freezes
the basket so the exact selection survives later toggling.
"""

import json

from fastapi import APIRouter, Depends, Request
from sqlalchemy import func, select
from sqlalchemy.dialects.postgresql import insert as pg_insert
from sqlalchemy.orm import Session

from app.db import get_db
from app.models import QuoteRequest, QuoteSelection
from app.services import identity
from app.models.schemas import (
    QuoteRequestIn,
    QuoteRequestOut,
    QuoteSelectionIn,
    QuoteSelectionOut,
)

router = APIRouter(prefix="/api/quote", tags=["quote"])


@router.get("/selections", response_model=list[QuoteSelectionOut])
def list_selections(db: Session = Depends(get_db)) -> list[QuoteSelection]:
    return list(db.scalars(select(QuoteSelection).order_by(QuoteSelection.item_key)))


@router.post("/selections", response_model=QuoteSelectionOut)
def set_selection(payload: QuoteSelectionIn, request: Request, db: Session = Depends(get_db)) -> QuoteSelection:
    """ON CONFLICT so rapid toggling cannot race a SELECT-then-INSERT into a 500. The
    author is the session's effective account."""
    who = identity.actor(request)
    stmt = (
        pg_insert(QuoteSelection)
        .values(item_key=payload.item_key, included=payload.included, author=who.display_name, author_id=who.id)
        .on_conflict_do_update(
            index_elements=[QuoteSelection.item_key],
            set_={
                "included": payload.included,
                "author": who.display_name,
                "author_id": who.id,
                "updated_at": func.now(),
            },
        )
    )
    db.execute(stmt)
    db.commit()
    row = db.scalar(select(QuoteSelection).where(QuoteSelection.item_key == payload.item_key))
    assert row is not None
    return row


@router.get("/requests", response_model=list[QuoteRequestOut])
def list_requests(db: Session = Depends(get_db)) -> list[QuoteRequest]:
    return list(db.scalars(select(QuoteRequest).order_by(QuoteRequest.created_at.desc())))


@router.post("/requests", response_model=QuoteRequestOut, status_code=201)
def add_request(payload: QuoteRequestIn, request: Request, db: Session = Depends(get_db)) -> QuoteRequest:
    who = identity.actor(request)
    row = QuoteRequest(
        author=who.display_name,
        author_id=who.id,
        note=(payload.note or "").strip() or None,
        items=json.dumps(payload.items),
        total_usd=payload.total_usd,
    )
    db.add(row)
    db.commit()
    db.refresh(row)
    return row
