#!/usr/bin/env python3
"""Вернуть панели её подписи из единого источника.

Зачем. Наборы `панель/данные/*.json` правят сразу с нескольких сторон:
скрипты завода, ручные правки, параллельные сессии. Цифры и строки таблиц
пересобираются легко, а «человеческие» пояснения при чужой перезаписи
молча откатываются к старым. Так 04.09.2026 в разделе «Статьи» снова
появилось «Домена нет, аккаунтов на площадках нет», хотя домен работал
третий день.

Поэтому все такие тексты живут в одном файле `подписи.json`, а этот скрипт
накатывает их поверх наборов. Он вызывается из `обновить-фолбэк.py`, то есть
срабатывает при каждой сборке панели — вручную звать не нужно.

В текстах можно ставить подстановки, они считаются из реестра:
    {портал}    - сколько статей опубликовано на портале
    {площадки}  - сколько материалов вышло на внешних площадках
    {всего}     - сколько текстов написано всего
    {сегодня}   - дата сборки панели в виде 2026-09-07
    {месяц}     - текущий месяц словами: «сентябрь 2026»
    {запросов}  - запросов в последней выгрузке Вебмастера
    {показы}    - показов в выдаче за две недели
    {клики}     - кликов из выдачи за две недели
    {показы_фраза}, {клики_фраза} - то же со склонением: «49 показов», «1 клик»
    {гео_замеров}   - сколько прогонов GEO-монитора уже было
    {гео_дата}      - дата последнего прогона в виде 14.09.2026
    {гео_процент}   - доля ответов со ссылкой на наш домен

Запуск (обычно не нужен, вызывается сам):
    python3 панель/данные/применить-подписи.py
"""

import json
from datetime import date
from pathlib import Path

ДАННЫЕ = Path(__file__).resolve().parent
ПЛАН = Path(__file__).resolve().parent / "contentplan.json"
ИСТОЧНИК = ДАННЫЕ / "подписи.json"
РЕЕСТР = ДАННЫЕ.parent.parent / "завод" / "реестр-текстов.json"
ВЕБМАСТЕР = ДАННЫЕ.parent.parent / "завод" / "вебмастер" / "история"
ОТЧЁТ = ДАННЫЕ / "report.json"

МЕСЯЦЫ = ("января февраля марта апреля мая июня июля "
          "августа сентября октября ноября декабря").split()
МЕСЯЦЫ_ИМ = ("январь февраль март апрель май июнь июль "
             "август сентябрь октябрь ноябрь декабрь").split()


def склонение(н, один, два, много):
    н = abs(int(н))
    if н % 10 == 1 and н % 100 != 11:
        return один
    if 2 <= н % 10 <= 4 and not 12 <= н % 100 <= 14:
        return два
    return много


def из_вебмастера():
    """Числа последней выгрузки. Нет выгрузки - нет и подстановок."""
    снимки = sorted(ВЕБМАСТЕР.glob("*.json")) if ВЕБМАСТЕР.exists() else []
    if not снимки:
        return {"запросов": 0, "показы": 0, "клики": 0}
    д = json.loads(снимки[-1].read_text(encoding="utf-8"))
    строки = д.get("строки", [])
    показы = int(sum(с.get("показы") or 0 for с in строки))
    клики = int(sum(с.get("клики") or 0 for с in строки))
    # Готовые обороты со склонением: в тексте «1 кликов» читается как опечатка.
    return {"запросов": len(строки), "показы": показы, "клики": клики,
            "показы_фраза": f"{показы} {склонение(показы, 'показ', 'показа', 'показов')}",
            "клики_фраза": f"{клики} {склонение(клики, 'клик', 'клика', 'кликов')}"}


def из_гео():
    """Числа контура GEO. Раньше подпись сводного отчёта говорила «GEO замерен
    один раз, 08.09.2026» - это было вписано словами и устарело после второго
    прогона 14.09 (найдено 15.09.2026)."""
    if not ОТЧЁТ.exists():
        return {}
    geo = json.loads(ОТЧЁТ.read_text(encoding="utf-8")).get("geo") or {}
    история = geo.get("история") or []
    если_нет = {"гео_замеров": 0, "гео_дата": "замера не было", "гео_процент": "-"}
    if not история:
        return если_нет
    последний = история[-1]
    return {"гео_замеров": len(история),
            "гео_дата": ".".join(reversed(последний["дата"].split("-"))),
            "гео_процент": (int(п) if (п := последний.get("процент", 0)) == int(п) else п)}


def подстановки():
    if not РЕЕСТР.exists():
        return {}
    р = json.loads(РЕЕСТР.read_text(encoding="utf-8"))
    # статус пишется по-разному: «опубликовано на Spark 04.09» и «ОПУБЛИКОВАНО
    # 11.09.2026 руководителем». Сравнение без учёта регистра: с ним подпись
    # 14.09.2026 показывала 6 публикаций вместо 10, теряя все, где статус
    # набран заглавными.
    портал = sum(1 for т in р["тексты"]
                 if "опубликовано на портале" in т["статус"].lower())
    # «не видно читателям» не считаем публикацией: так же поступает
    # обновить-площадки.py, и иначе подпись и сводный отчёт расходятся
    # на единицу (случай с записью в LiveJournal).
    площадки = sum(1 for т in р["тексты"]
                   if т["вид"] == "внешняя площадка"
                   and "опубликовано" in т["статус"].lower()
                   and "не видно читателям" not in т["статус"].lower())
    сегодня = date.today()
    # Состав очереди контент-плана: чтобы подпись раздела не приходилось
    # править руками после каждой публикации (15.09.2026).
    из_плана = {}
    if ПЛАН.exists():
        оч = json.loads(ПЛАН.read_text(encoding="utf-8")).get("очередь", [])
        живые = [п for п in оч if not п.get("демо")]
        из_плана = {
            "позиций": len(живые),
            "опубликовано": sum(1 for п in живые if п.get("статус") == "Опубликована"),
            "отложено": sum(1 for п in живые if п.get("статус") == "Отложена"),
            "в_работе": sum(1 for п in живые
                            if п.get("статус") in ("В плане", "Запланирована")),
        }
    числа = {"портал": портал, "площадки": площадки, "всего": р["итоги"]["всего"],
             "сегодня": сегодня.isoformat(),
             "месяц": "%s %d" % (МЕСЯЦЫ_ИМ[сегодня.month - 1], сегодня.year)}
    числа.update(из_плана)
    числа.update(из_вебмастера())
    числа.update(из_гео())
    return числа


def главная():
    if not ИСТОЧНИК.exists():
        return print("нет %s: подписи не заданы" % ИСТОЧНИК.name)
    подписи = json.loads(ИСТОЧНИК.read_text(encoding="utf-8"))
    числа = подстановки()
    возвращено = []

    for набор, поля in подписи.items():
        if набор.startswith("_"):
            continue
        файл = ДАННЫЕ / (набор + ".json")
        if not файл.exists():
            print("  пропускаю %s: файла нет" % набор)
            continue
        д = json.loads(файл.read_text(encoding="utf-8"))
        д.setdefault("мета", {})
        изменено = False
        for ключ, текст in поля.items():
            свежий = текст.format(**числа) if числа else текст
            if д["мета"].get(ключ) != свежий:
                д["мета"][ключ] = свежий
                изменено = True
                возвращено.append("%s.%s" % (набор, ключ))
        if изменено:
            файл.write_text(json.dumps(д, ensure_ascii=False, indent=1), encoding="utf-8")

    if возвращено:
        print("подписи восстановлены:", ", ".join(возвращено))
    else:
        print("подписи на месте, править нечего")


if __name__ == "__main__":
    главная()
