"""Тексты системных уведомлений (ТЗ 3.21).

Строки собирает сервер, а не service worker: воркер живёт между сессиями и не
знает ни языка пользователя, ни его настроек — у него нет ни бандла локалей, ни
запроса, из которого язык можно взять. Поэтому ru/en/uk живут здесь и осознанно
дублируют фронтовые `gamify.claimed`/`gamify.review`: тост и системное
уведомление говорят об одном и том же разными словами.

Язык разрешается той же цепочкой, что и на фронте (`i18n/locale.ts`): ручное
переопределение в настройках → локаль SSO → «ru».
"""

from sqlalchemy.orm import Session

from app.models import AppSetting, User

# Тот же ключ, что `LANGUAGE_KEY` в api/settings.py: импортировать оттуда значило бы
# развернуть зависимость «сервис → API» ради одного строкового литерала
LANGUAGE_KEY = "language"
DEFAULT_LANGUAGE = "ru"
# Языки, для которых есть строки; всё остальное — «ru»
SUPPORTED = ("ru", "en", "uk")

AGENT_FALLBACK: dict[str, str] = {
    "ru": "ИИ-агент",
    "en": "the AI agent",
    "uk": "ШІ-агент",
}

# kind → язык → (заголовок, тело). Плейсхолдеры подставляются через str.format
TEXTS: dict[str, dict[str, tuple[str, str]]] = {
    "task.claimed": {
        "ru": (
            "Агент взял задачу в работу",
            "«{title}» — {name} взялась за дело, не трогайте её, пока работает",
        ),
        "en": (
            "An agent took the task",
            "“{title}” — {name} got to work, leave it alone while she works",
        ),
        "uk": (
            "Агент узяв завдання в роботу",
            "«{title}» — {name} взялася до справи, не чіпайте його, поки працює",
        ),
    },
    "task.review": {
        "ru": (
            "Работа ждёт приёмки",
            "«{title}» — посмотрите, что сделано, и примите или верните",
        ),
        "en": (
            "Work awaits review",
            "“{title}” — check what was done, then accept or return it",
        ),
        "uk": (
            "Робота чекає на приймання",
            "«{title}» — подивіться, що зроблено, і прийміть або поверніть",
        ),
    },
}

# Тексты уведомления живут секунды на экране блокировки — длинное тело в нём не
# читают, а усекать его по дороге обиднее, чем обрезать здесь
MAX_TITLE = 60
MAX_BODY = 140


def user_language(db: Session, user_id: str) -> str:
    """Язык уведомлений пользователя: настройка → локаль SSO → «ru».

    Настройка читается напрямую, а не через `api/settings.py`: импортировать роутер
    в сервис значило бы завести обратную зависимость, а правило — три строки.
    """
    row = db.get(AppSetting, (user_id, LANGUAGE_KEY))
    if row is not None and row.value in SUPPORTED:
        return row.value
    user = db.get(User, user_id)
    locale = (user.locale or "") if user is not None else ""
    # SSO отдаёт локали вида «ru-RU»: берём язык, отбрасывая регион
    language = locale.replace("_", "-").split("-")[0].lower()
    return language if language in SUPPORTED else DEFAULT_LANGUAGE


def _clip(text: str, limit: int) -> str:
    if len(text) <= limit:
        return text
    return text[: limit - 1].rstrip() + "…"


def render(kind: str, language: str, **fields: str) -> tuple[str, str] | None:
    """Собрать (заголовок, тело) для события; неизвестный kind → None.

    Заголовок задачи усекаем: он приходит от пользователя (до 500 символов), а
    системное уведомление длиннее пары строк всё равно не показывает.
    """
    variants = TEXTS.get(kind)
    if variants is None:
        return None
    title, body = variants.get(language, variants[DEFAULT_LANGUAGE])
    fields.setdefault("name", AGENT_FALLBACK.get(language, AGENT_FALLBACK[DEFAULT_LANGUAGE]))
    if "title" in fields:
        fields["title"] = _clip(fields["title"], MAX_TITLE)
    return title, _clip(body.format(**fields), MAX_BODY)
