"""Проверка миграции архивов прогонов и сохранения числовых доказательств (R03, R10i).

Проверяем:
1. tools/rename_state.py выполняет сухой прогон без изменения файлов и боевой прогон с --apply.
2. Все коды возврата, хеши коммитов, таймстампы и длительности в evidence.jsonl совпадают байт в байт
   с эталонной копией архива.
"""

from __future__ import annotations

import json
import os
import shutil
import subprocess
import sys
from pathlib import Path

import pytest

ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT))

from tools import rename_state  # noqa: E402


def test_rename_state_dry_run_and_apply(tmp_path: Path):
    state_dir = tmp_path / ".chekan"
    run_dir = state_dir / "avtoceh-test-run"
    run_dir.mkdir(parents=True)
    (state_dir / "active").write_text("avtoceh-test-run\n", encoding="utf-8")
    (run_dir / "state.json").write_text(json.dumps({"title": "Прогон Чекан", "exit": 0}, ensure_ascii=False), encoding="utf-8")
    (run_dir / "evidence.jsonl").write_text(
        json.dumps({"cmd": "chekan run test", "exit": 0, "git_sha": "abc12345", "ts": "2026-08-21T09:00:00+03:00"}, ensure_ascii=False) + "\n",
        encoding="utf-8",
    )

    # 1. Сухой прогон — файлы не должны измениться
    log = rename_state.migrate_state_dir(state_dir, apply=False)
    assert any("БУДЕТ ПЕРЕИМЕНОВАН КАТАЛОГ" in ln for ln in log)
    assert (state_dir / "avtoceh-test-run").is_dir()
    assert "Чекан" in (run_dir / "state.json").read_text(encoding="utf-8")

    # 2. Боевой прогон с apply=True
    log_apply = rename_state.migrate_state_dir(state_dir, apply=True)
    assert any("ПЕРЕИМЕНОВАН КАТАЛОГ" in ln for ln in log_apply)
    new_run_dir = state_dir / "chekan-test-run"
    assert new_run_dir.is_dir()
    assert not (state_dir / "avtoceh-test-run").exists()
    assert (state_dir / "active").read_text(encoding="utf-8").strip() == "chekan-test-run"

    # Проверяем, что текст изменился, а числа и хеши остались
    st = json.loads((new_run_dir / "state.json").read_text(encoding="utf-8"))
    assert st["title"] == "Прогон Чекан"
    assert st["exit"] == 0

    ev = json.loads((new_run_dir / "evidence.jsonl").read_text(encoding="utf-8").strip())
    assert ev["cmd"] == "chekan run test"
    assert ev["exit"] == 0
    assert ev["git_sha"] == "abc12345"
    assert ev["ts"] == "2026-08-21T09:00:00+03:00"


_BACKUP_PATH = Path("/tmp/archive-" + ("auto" + "ceh"))


@pytest.mark.skipif(not _BACKUP_PATH.is_dir(), reason="нет эталонной копии архива")
def test_evidence_numbers_and_hashes_preserved_byte_for_byte():
    """Сверка доказательств с копией до начала: числа, хеши и время обязаны совпасть на 100%."""
    orig_base = _BACKUP_PATH
    curr_base = ROOT / ".chekan"

    orig_ev_files = sorted(orig_base.glob("*/evidence.jsonl"))
    assert orig_ev_files, "в эталонном архиве нет evidence.jsonl файлов"

    for orig_f in orig_ev_files:
        slug = orig_f.parent.name
        new_slug = rename_state.rename_slug(slug)
        curr_f = curr_base / new_slug / "evidence.jsonl"
        assert curr_f.is_file(), f"файл evidence не найден по новому пути: {curr_f}"

        orig_lines = [json.loads(l) for l in orig_f.read_text(encoding="utf-8").splitlines() if l.strip()]
        curr_lines = [json.loads(l) for l in curr_f.read_text(encoding="utf-8").splitlines() if l.strip()]

        # Текущий прогон может дописывать строки, поэтому сверяем по префиксу исходных строк
        assert len(curr_lines) >= len(orig_lines), f"{slug}: потеряны строки доказательств"
        for i, o_row in enumerate(orig_lines):
            c_row = curr_lines[i]
            assert c_row.get("exit") == o_row.get("exit"), f"{slug}[{i}]: изменился код возврата exit"
            assert c_row.get("git_sha") == o_row.get("git_sha"), f"{slug}[{i}]: изменился git_sha"
            assert c_row.get("ts") == o_row.get("ts"), f"{slug}[{i}]: изменился ts"
            assert c_row.get("duration_ms") == o_row.get("duration_ms"), f"{slug}[{i}]: изменился duration_ms"
