"""Static guards for migration 164 (issue #2235).

Прод применяет data/sql построчно строго (ON_ERROR_STOP). Полный DB-прогон
идемпотентности требует живой БД; здесь мы фиксируем структурные инварианты,
которые ГАРАНТИРУЮТ идемпотентность и НЕдеструктивность по построению:

  1. Транзакционность (BEGIN/COMMIT) — атомарный апдейт.
  2. Идемпотентность: апдейт ограничен строками, чей source_url ещё НЕ канонический
     (`source_url <> '…offer/'||source_id||'/'`) И входит в группу с >1 строкой
     (CTE `shared`, HAVING count(*)>1). После первого прогона таких строк нет →
     повторный прогон = no-op.
  3. НЕдеструктивность: миграция канонизирует source_url, а НЕ гасит строки —
     `is_active = false` в файле быть НЕ должно (защита от регресса к
     деструктивному «схлопыванию», отвергнутому по данным: дубли — это РАЗНЫЕ
     офферы, не дубли-строки).
  4. Скоуп — только yandex.
"""

from __future__ import annotations

import re
from pathlib import Path

_SQL_DIR = Path(__file__).resolve().parents[1] / "data" / "sql"
_MIGRATION_164 = _SQL_DIR / "164_yandex_url_canonicalize_active_dups.sql"


def _sql() -> str:
    return _MIGRATION_164.read_text(encoding="utf-8")


def _executable_sql() -> str:
    """SQL без комментариев — только исполняемые строки (`--`-комменты вырезаны).

    Заголовок миграции в прозе объясняет, ПОЧЕМУ отвергнуто «схлопывание»
    (is_active=false), поэтому destructive-проверки должны смотреть на код, а не
    на комментарии. В этой миграции `--` не встречается внутри строковых литералов.
    """
    lines = []
    for raw in _MIGRATION_164.read_text(encoding="utf-8").splitlines():
        code = raw.split("--", 1)[0]
        if code.strip():
            lines.append(code)
    return "\n".join(lines)


def _flat(text: str) -> str:
    return re.sub(r"\s+", " ", text).strip()


def test_migration_164_exists() -> None:
    assert _MIGRATION_164.exists(), f"missing migration: {_MIGRATION_164}"


def test_migration_164_is_transactional() -> None:
    sql = _sql()
    assert "BEGIN;" in sql
    assert "COMMIT;" in sql


def test_migration_164_is_idempotent_by_construction() -> None:
    """Апдейт исключает уже-канонические строки → повторный прогон no-op."""
    flat = _flat(_executable_sql())
    # Группировка дублей (HAVING count(*) > 1) + пропуск уже-канонических строк.
    assert "having count(*) > 1" in flat.lower()
    assert "source_url <> 'https://realty.yandex.ru/offer/'" in flat


def test_migration_164_is_non_destructive() -> None:
    """Канонизация source_url, НЕ гашение строк: никакого is_active=false в коде."""
    flat = _flat(_executable_sql()).lower()
    assert "is_active = false" not in flat
    assert "is_active=false" not in flat
    # Мутируется именно source_url.
    assert "set source_url = 'https://realty.yandex.ru/offer/'" in flat


def test_migration_164_scoped_to_yandex_active() -> None:
    flat = _flat(_executable_sql())
    assert "l.source = 'yandex'" in flat
    assert "l.is_active" in flat
    # Только числовой yandex offerId идёт в канонический URL.
    assert "l.source_id ~ '^[0-9]+$'" in flat
