"""Administration for the cards offered on the new-chat screen."""

from __future__ import annotations

import logging

from fastapi import APIRouter, Form, HTTPException, Request, Response, status
from fastapi.responses import RedirectResponse

from lembas.api.deps import AdminUser, Db
from lembas.db.models import Suggestion
from lembas.services import suggestions as suggestions_service
from lembas.web.templating import render

log = logging.getLogger(__name__)

router = APIRouter(prefix="/admin/suggestions", tags=["admin-suggestions"])


def _suggestion(db: Db, suggestion_id: str) -> Suggestion:
    suggestion = db.get(Suggestion, suggestion_id)
    if suggestion is None:
        raise HTTPException(status.HTTP_404_NOT_FOUND, "That suggestion no longer exists.")
    return suggestion


def _back(message: str = "") -> Response:
    target = f"/admin/suggestions?saved={message}" if message else "/admin/suggestions"
    return RedirectResponse(target, status_code=status.HTTP_303_SEE_OTHER)


@router.get("")
async def suggestions_page(request: Request, db: Db, user: AdminUser, saved: str = ""):
    rows = suggestions_service.all_of_them(db)
    return render(
        request,
        "admin/suggestions.html",
        {
            "suggestions": rows,
            "at_limit": len(rows) >= suggestions_service.MAX_SUGGESTIONS,
            "max_suggestions": suggestions_service.MAX_SUGGESTIONS,
            "max_shown": suggestions_service.MAX_SHOWN,
            "saved": saved,
        },
    )


@router.post("")
async def create_suggestion(
    db: Db,
    user: AdminUser,
    name: str = Form(""),
    description: str = Form(""),
    prompt: str = Form(""),
) -> Response:
    name = name.strip()
    if not name:
        return _back("A suggestion needs a name.")
    if len(suggestions_service.all_of_them(db)) >= suggestions_service.MAX_SUGGESTIONS:
        return _back(f"That is already {suggestions_service.MAX_SUGGESTIONS}, which is plenty.")

    suggestions_service.create(db, name=name, description=description, prompt=prompt)
    log.info("%s added suggestion %s", user.email, name)
    return _back(f"Added {name}.")


# Registered before /{suggestion_id}: FastAPI matches in registration order, so
# with the parameterised route first any literal segment added later would be
# captured as an id. That has already been a bug once, in /admin/models.
@router.post("/{suggestion_id}/delete")
async def delete_suggestion(db: Db, user: AdminUser, suggestion_id: str) -> Response:
    suggestion = _suggestion(db, suggestion_id)
    name = suggestion.name
    db.delete(suggestion)
    db.commit()
    log.info("%s deleted suggestion %s", user.email, name)
    return _back(f"Deleted {name}.")


@router.post("/{suggestion_id}")
async def update_suggestion(
    request: Request,
    db: Db,
    user: AdminUser,
    suggestion_id: str,
) -> Response:
    """Save one row.

    The raw form is read rather than declared parameters because `enabled` is a
    checkbox: FastAPI cannot tell an unticked box from an absent field, and an
    absent one is exactly what an unticked box sends.
    """
    suggestion = _suggestion(db, suggestion_id)
    form = await request.form()

    suggestion.name = (
        str(form.get("name") or "").strip()[: suggestions_service.MAX_NAME] or suggestion.name
    )
    suggestion.description = str(form.get("description") or "").strip()[
        : suggestions_service.MAX_DESCRIPTION
    ]
    suggestion.prompt = str(form.get("prompt") or "").replace("\r\n", "\n")[
        : suggestions_service.MAX_PROMPT
    ]
    suggestion.enabled = "enabled" in form

    position = str(form.get("position") or "").strip()
    if position.isdigit():
        suggestion.position = min(max(int(position) - 1, 0), 999)

    db.commit()
    log.info("%s updated suggestion %s", user.email, suggestion.name)
    return _back(f"Saved {suggestion.name}.")
