"""REC-239: a corrupt-but-present board sidecar must fail loud instead of
silently collapsing to {} and emitting default "proposed" review state.

`_read_json_dict` is the exact swallow site; `_resolve_board_sidecar` is the
user-facing board endpoint that consumed the silent default.
"""

import json

import pytest

from recoil.core.exceptions import SidecarCorruptError
from recoil.workspace import board


def test_missing_sidecar_returns_empty(tmp_path):
    # No file written -> graceful {} (board PNG may exist with no sidecar yet).
    assert board._read_json_dict(tmp_path / "absent.png.json") == {}


def test_valid_sidecar_returns_dict(tmp_path):
    p = tmp_path / "b.png.json"
    p.write_text(json.dumps({"artifact": "b.png", "status": "approved"}))
    assert board._read_json_dict(p) == {"artifact": "b.png", "status": "approved"}


def test_corrupt_sidecar_raises(tmp_path):
    # Present but malformed JSON — the case that previously returned {} and
    # silently produced default board metadata.
    p = tmp_path / "b.png.json"
    p.write_text("{bad json,,,")
    with pytest.raises(SidecarCorruptError):
        board._read_json_dict(p)


def test_non_dict_sidecar_raises(tmp_path):
    # Valid JSON but not an object — also an unusable sidecar.
    p = tmp_path / "b.png.json"
    p.write_text(json.dumps(["not", "a", "dict"]))
    with pytest.raises(SidecarCorruptError):
        board._read_json_dict(p)


def test_resolve_board_sidecar_propagates_corruption(tmp_path):
    # End-to-end: a pointed board whose sidecar on disk is corrupt must surface
    # the error to the board endpoint, not silently return "proposed".
    artifact = "boards/EP001_SH02_board_v1.png"
    sidecar = tmp_path / f"{artifact}.json"
    sidecar.parent.mkdir(parents=True, exist_ok=True)
    sidecar.write_text("{corrupt")
    with pytest.raises(SidecarCorruptError):
        board._resolve_board_sidecar(tmp_path, {"artifact": artifact})
