#!/usr/bin/env python3
"""Подтянуть в таблицу «Статьи» панели то, что реально написано.

Панель показывает очередь контент-плана, а состояние текстов живёт в их
frontmatter. Разойтись эти две вещи могут за день: статья написана, а в панели
у неё по-прежнему «Запланирована». Скрипт закрывает разрыв в одну сторону -
из файлов в панель, и только по трём полям: статус, ссылка, файл.

Строки, которых в таблице нет (материалы для внешних площадок, статьи вне
волны), добавляются с номерами от 22. Демо-строки (номера от 101) не трогаются:
они нарисованные, их задача показывать, как таблица выглядит с данными.

Запуск: python3 панель/данные/обновить-статьи.py
Перед запуском пересобрать реестр: python3 завод/реестр-текстов.py
"""

import json
from pathlib import Path

КОРЕНЬ = Path(__file__).resolve().parent.parent.parent
РЕЕСТР = КОРЕНЬ / "завод" / "реестр-текстов.json"
ТАБЛИЦА = КОРЕНЬ / "панель" / "данные" / "articles.json"
ВИТРИНА = "https://smm.prfabrika.ru/"
ПОРТАЛ = "https://frantlas.ru/statya/"

# frontmatter пишется по-человечески, панель живёт на своей легенде статусов.
# Порядок важен: срабатывает первое совпадение, поэтому частные формулировки
# стоят выше общих. Текст, отправленный в редакцию, это «На модерации», а не
# «Готова» и не «Черновик»: разница в том, ждём мы себя или чужого редактора.
СТАТУСЫ = (("опубликован", "Опубликовано"),
           ("отправлено в редакцию", "На модерации"),
           ("ждёт ответа редакции", "На модерации"),
           ("ждём ответа", "На модерации"),
           ("не публиковать", "Черновик готов"),
           ("регистрация", "Отложена"),
           ("отложен", "Ждёт решения"),
           ("ждёт ответа", "Готова"),
           ("к публикации", "Готова"))

# площадка у материала берётся из его шапки, а кластер там не указывают:
# тему площадочного текста привязываем к кластеру портала вручную, по смыслу
КЛАСТЕР_ПЛОЩАДКИ = {
    "cossa-01-kak-prodayut-franshizy.md": ("А25", "исследование"),
    "дзен-01-proverka-franchaizera.md": ("А13", "прогрев"),
    "tzh-01-chto-vidno-do-pokupki.md": ("А14", "прогрев"),
    "vc-01-poryadok-oshibok.md": ("Б9", "разбор"),
    "pikabu-01-proverka-prishla.md": ("Б29", "прогрев"),
    "smartlab-01-okupaemost-franshizy.md": ("А17", "разбор"),
    "smartlab-02-biznes-plan-ne-shoditsya.md": ("Б14", "разбор"),
    "spark-01-podderzhka-po-reestram.md": ("Б18", "инструкция"),
    "audit-it-01-dogovor-franshizy-uchet.md": ("А14", "разбор"),
    "lj-01-okupaemost-schital-sam.md": ("А17", "прогрев"),
}


def образец(строки):
    """Пустая строка таблицы: берём поля существующей, чтобы колонки совпали."""
    пустая = {к: None for к in строки[0]}
    пустая.update({"рубрика": "Франшизы", "контур": "спутник · разбор", "приоритет": "P1",
                   "неделя": "-", "волна": "П1", "просмотры": None, "демо": False,
                   "ключи": [], "ключи_кластер": None, "ключи_замер": None,
                   "ключи_нота": "частотность не мерена"})
    return пустая


def главная():
    реестр = json.loads(РЕЕСТР.read_text(encoding="utf-8"))
    данные = json.loads(ТАБЛИЦА.read_text(encoding="utf-8"))
    строки = данные["строки"]
    живые = [с for с in строки if not с.get("демо")]
    изменено, добавлено = [], []

    for текст in реестр["тексты"]:
        имя = Path(текст["файл"]).name
        низ = текст["статус"].lower()
        статус = next((з for сл, з in СТАТУСЫ if сл in низ), "Черновик готов")
        # ссылка в панели ведёт туда, где текст лежит для читателя: на площадку,
        # если он вышел, на портал, если опубликован там, и только для черновиков
        # на витрину. Раньше всё вело на витрину, и опубликованное выглядело
        # неопубликованным
        ссылка = (ВИТРИНА + текст["на_витрине"][0]) if текст["на_витрине"] else None
        if текст.get("ссылка"):
            ссылка = текст["ссылка"]
        elif "опубликовано на портале" in низ and текст.get("слаг"):
            ссылка = ПОРТАЛ + текст["слаг"] + "/"
        площадочный = текст["вид"] == "внешняя площадка"
        кластер, тип = КЛАСТЕР_ПЛОЩАДКИ.get(имя, ("", "разбор"))

        if площадочный:
            строка = next((с for с in живые if с.get("файл") == текст["файл"]), None)
        else:
            строка = next((с for с in живые if с.get("кластер") == текст["кластер"]
                           and с["площадка"].startswith("портал")), None)

        if строка is None:
            строка = образец(строки)
            строка.update({
                "№": max(с["№"] for с in строки if с["№"] < 100) + 1,
                "заголовок": текст["заголовок"],
                "кластер": кластер if площадочный else текст["кластер"],
                "площадка": текст["площадка"] or "портал frantlas.ru",
                "тип": тип if площадочный else "разбор",
                "создана": текст["написано"] or реестр["собрано"],
            })
            строки.append(строка)
            живые.append(строка)
            добавлено.append(f'{строка["№"]} {строка["заголовок"][:40]} ({строка["площадка"]})')

        # Сколько иллюстраций у материала: в эталоне PR Factory под это отдельная
        # колонка «🖼» (сверено 14.09.2026). Обновляем на каждом прогоне, а не
        # только при создании строки: картинки часто добавляются после текста.
        строка["иллюстраций"] = len(текст.get("иллюстрации") or [])

        было = (строка.get("статус"), строка.get("ссылка"), строка.get("файл"))
        строка["статус"] = статус
        строка["ссылка"] = ссылка
        строка["файл"] = текст["файл"]
        if было != (статус, ссылка, текст["файл"]) and строка["№"] not in [int(д.split()[0]) for д in добавлено]:
            изменено.append(f'{строка["№"]} {строка["заголовок"][:40]}: {было[0]} → {статус}')

    строки.sort(key=lambda с: с["№"])
    данные["мета"]["источник"] = ("семантика/контент-план-волна-1.md · состояние текстов из "
                                 "завод/реестр-текстов.json (собирается из frontmatter файлов)")
    данные["мета"]["состояние_завода"] = (
        f'написано текстов: {реестр["итоги"]["всего"]} '
        f'({реестр["итоги"]["для_портала"]} для портала, '
        f'{реестр["итоги"]["для_внешних_площадок"]} для внешних площадок), опубликовано: '
        f'{реестр["итоги"]["опубликовано"]}')
    for п in ("Cossa", "Т-Ж Сообщество"):
        if п not in данные["мета"]["площадки"]:
            данные["мета"]["площадки"].append(п)

    ТАБЛИЦА.write_text(json.dumps(данные, ensure_ascii=False, indent=1), encoding="utf-8")
    print("обновлено строк:", len(изменено))
    for с in изменено:
        print("  ", с)
    print("добавлено строк:", len(добавлено))
    for с in добавлено:
        print("  ", с)


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