"""Каноникализация имени склада — Python-зеркало SQL-выражения warehouse_canon.

ЕДИНЫЙ источник правды для нормализации в SQL — генерируемая колонка
fact_stocks_daily.warehouse_canon (kernel_fact_layer.sql). Эта функция ПОВТОРЯЕТ ту же
семантику для тестов (проверить, что варианты написания схлопываются) и для валидатора
контракта (Слой 4). Любая правка SQL-выражения должна синхронно править эту функцию —
за этим следит tests/test_canon.py (набор пар variant→canon).

Семантика (как в SQL): схлопнуть пробелы → унифицировать « / »→«/» → trim → lower.
"""
from __future__ import annotations

import re

_WS = re.compile(r"\s+")
_SLASH = re.compile(r"\s*/\s*")


def warehouse_canon(name: str | None) -> str:
    """Нормализованное имя склада (ключ дедупа). None/'' → ''."""
    s = _WS.sub(" ", name or "")
    s = _SLASH.sub("/", s)
    return s.strip().lower()


# ─── Realized-статусы (ПРОДАНО) — ЕДИНАЯ точка правды ────────────────────────
# Словарь «mp_id → realized-статус» и «первичный mp → группа суб-mp» жил в трёх
# копиях нового контура (_RATING_MP_SPEC в build_fact_rating, PRIMARY_GROUPS в
# build_fact_turnover, _REALIZED_STATUS в data_api/reports/shipment.py). Сведён
# сюда (epic-05/08). Значения = фактические из data_api shipment._REALIZED_STATUS
# (источник значений на момент выноса) — поведение НЕ меняется (дельта = 0).
#
# Рейтинг/прогноз/оборачиваемость считаются по ПРОДАННОМУ (RATING_FORMULA_v2 §4.1),
# не по всем заказам: WB='sale' (wb_sales, for_pay после комиссии; снимает двойной
# счёт заказ/выкуп), Ozon='delivered', YM='DELIVERED', Lamoda='Delivered',
# Gold Apple='delivered'.
#
# Золотое яблоко (12.08.2026) участвует и в рейтинге. Прежде оно было только в
# отгрузке — и не потому, что так решили, а потому, что считать было нечем: у
# всех строк mp 10 колонка source_status стояла пустой, признак «продано» не
# ставился ни разу, и рейтинг от проданного выходил нулевым. Теперь проекция
# пишет и слово площадки, и выручку.
#
# Оговорка, которая остаётся: источник Золотого яблока — СКОЛЬЗЯЩАЯ СВОДКА по
# артикулу за окно, а не датированные события. Поэтому все строки одного
# прогона несут одну дату — день снимка, — и история по дням у него не
# восстанавливается: за прошлый месяц видно итог, а не распределение по дням.
# Для месячного рейтинга этого достаточно, для суточных разрезов нет.
# Девять realized mp; mp_id=7 YM-Express в kernel отсутствует.
REALIZED_STATUS: dict[int, str] = {
    1: "sale", 2: "sale",
    3: "delivered", 4: "delivered", 5: "delivered",
    6: "DELIVERED", 8: "DELIVERED",
    9: "Delivered",
    10: "delivered",
}

# Первичный mp_id группы → суб-mp группы (getRelatedMpIds / PRIMARY_MP_IDS legacy).
# WB 1←{1,2}, Ozon 3←{3,4,5}, YM 6←{6,8}, Lamoda 9←{9}.
PRIMARY_GROUPS: dict[int, tuple[int, ...]] = {
    1: (1, 2),
    3: (3, 4, 5),
    6: (6, 8),
    9: (9,),
    10: (10,),
}
