"""The cards offered on the new-chat screen.

A blank composer is the least helpful thing a chat client can show someone who
has just installed one. These are three starting points an administrator can
replace with their own.
"""

from __future__ import annotations

import logging

from sqlalchemy import func, select
from sqlalchemy.orm import Session as DBSession

from lembas.db.models import Suggestion
from lembas.services import settings_store

log = logging.getLogger(__name__)

# A short list stays a short list. Past a dozen it is a menu, and a menu on the
# empty screen is a worse blank page than a blank page.
MAX_SUGGESTIONS = 12
MAX_SHOWN = 6

MAX_NAME = 120
MAX_DESCRIPTION = 300
MAX_PROMPT = 4000

# A card is sent the moment it is clicked, so each of these has to work cold --
# with nothing pasted and nothing typed. They are written to ask for what they
# need, which turns the first reply into the right question rather than a guess
# at material nobody has given yet.
#
# No Middle-earth flavour: this is functional UI.
DEFAULTS: tuple[tuple[str, str, str], ...] = (
    (
        "Explain this",
        "Get something confusing back in plain language.",
        "I want something explained in plain language. Ask me what it is, then "
        "give me one sentence summarising it, the details that actually matter, "
        "and anything I should watch out for.",
    ),
    (
        "Draft a reply",
        "Turn a message you have received into an answer you can send.",
        "I need to reply to a message. Ask me what it says, what tone I want and "
        "what outcome I am after, then write a draft I could send as it stands.",
    ),
    (
        "Find the flaw",
        "Have a plan argued with before you commit to it.",
        "I want a plan argued with. Ask me what the plan is, then tell me what is "
        "most likely to go wrong, what I am assuming without evidence, and what "
        "would change your mind. Do not soften it, and do not agree just because "
        "I sound confident.",
    ),
)

# Guards the seed. Not "is the table empty", because an administrator who
# deletes all three would get them back on every restart.
SEEDED_KEY = "suggestions_seeded"


def visible(db: DBSession) -> list[Suggestion]:
    """What the new-chat screen shows, in order."""
    return list(
        db.scalars(
            select(Suggestion)
            .where(Suggestion.enabled.is_(True))
            .order_by(Suggestion.position, Suggestion.name)
            .limit(MAX_SHOWN)
        )
    )


def all_of_them(db: DBSession) -> list[Suggestion]:
    """Every suggestion, enabled or not, for the admin page."""
    return list(
        db.scalars(select(Suggestion).order_by(Suggestion.position, Suggestion.name))
    )


def next_position(db: DBSession) -> int:
    """New rows land at the end rather than at 0, where they would shuffle.

    No `or -1` after the coalesce: position 0 is falsy, so that idiom sends the
    second row back to 0 on top of the first.
    """
    highest = db.scalar(select(func.coalesce(func.max(Suggestion.position), -1)))
    return int(highest if highest is not None else -1) + 1


def create(db: DBSession, *, name: str, description: str = "", prompt: str = "") -> Suggestion:
    suggestion = Suggestion(
        name=name.strip()[:MAX_NAME],
        description=description.strip()[:MAX_DESCRIPTION],
        prompt=prompt[:MAX_PROMPT],
        position=next_position(db),
    )
    db.add(suggestion)
    db.commit()
    return suggestion


def seed_defaults(db: DBSession) -> int:
    """Write the built-in suggestions, once ever.

    Runs from the startup housekeeping block. The flag is what makes it once:
    checking whether the table is empty would restore all three every restart
    for anyone who decided they did not want them.
    """
    if settings_store.get(db, SEEDED_KEY):
        return 0

    for name, description, prompt in DEFAULTS:
        create(db, name=name, description=description, prompt=prompt)

    settings_store.update(db, {SEEDED_KEY: True})
    log.info("seeded %d default suggestion(s)", len(DEFAULTS))
    return len(DEFAULTS)
