"""Char-sheet Brick 1 acceptance: role-qualified turn shelf slots resolve into a
multi-ref bundle (identity-first, is_hero only on the anchor), the filename helper
gains a view qualifier, and turn views never satisfy the identity gate."""
from pathlib import Path

from PIL import Image

from recoil.core.ref_stem import ref_filename
from recoil.core.ref_resolver import resolve_character_bundle
from recoil.core.ref_gate import assert_refs_complete
from recoil.core.ref_errors import MissingRequiredRefError
from recoil.core.paths import ProjectPaths
import pytest


def _png(p: Path) -> None:
    p.parent.mkdir(parents=True, exist_ok=True)
    Image.new("RGB", (8, 8)).save(p)


def _paths(tmp_path) -> ProjectPaths:
    return ProjectPaths(project_root=tmp_path / "fixture_project")


def test_ref_filename_view_qualifier():
    assert ref_filename("Wren", "identity") == "wren-identity.png"
    assert ref_filename("Wren", "turn", "png", view="front") == "wren-turn-front.png"
    assert ref_filename("Wren", "turn", "jpeg", view="profile") == "wren-turn-profile.jpeg"


def test_identity_only_when_no_turn_views(tmp_path):
    paths = _paths(tmp_path)
    look = paths.asset_look_dir("char", "wren")
    _png(look / "wren-identity.png")
    b = resolve_character_bundle(paths, "wren")
    assert [a.kind for a in b.assets] == ["identity"]
    assert b.hero_subjects() == frozenset({"wren"})


def test_bundle_includes_shelf_turn_views_identity_first(tmp_path):
    paths = _paths(tmp_path)
    look = paths.asset_look_dir("char", "wren")
    _png(look / "wren-identity.png")
    _png(look / "turn" / "wren-turn-front.png")
    _png(look / "turn" / "wren-turn-profile.png")
    b = resolve_character_bundle(paths, "wren")
    # identity anchor FIRST, then the turn views.
    assert b.assets[0].kind == "identity" and b.assets[0].is_hero is True
    turn = [a for a in b.assets if a.kind == "turn"]
    assert {a.view for a in turn} == {"front", "profile"}
    assert all(a.is_hero is False for a in turn), "turn views must NOT be heroes"
    assert all(a.role == "identity" for a in turn)
    # individual refs, never a composite
    assert len(b.paths()) == len(set(b.paths())) >= 3


def test_turn_views_do_not_satisfy_identity_gate(tmp_path):
    """A subject with ONLY turn views (no identity hero) still BLOCKS — the anchor
    stays mandatory (is_hero=False on turn views)."""
    paths = _paths(tmp_path)
    look = paths.asset_look_dir("char", "jade")
    _png(look / "turn" / "jade-turn-front.png")
    b = resolve_character_bundle(paths, "jade")
    with pytest.raises(MissingRequiredRefError):
        assert_refs_complete(shot_id="EP001_SH99", required_subjects=["JADE"],
                             bundle=b, board_gated=False, board_ref_path=None)


def test_bundle_ordering_and_cap(tmp_path):
    """Under maximal input (hero + fullbody + all 4 turn views), the bundle is exactly
    6, identity-first, then fullbody, then turn views; only the anchor is_hero; the
    'threequarter' canonical token is present. Asserts kinds/views/order, not just <=6."""
    paths = _paths(tmp_path)
    look = paths.asset_look_dir("char", "jade")
    _png(look / "jade-identity.png")
    _png(look / "jade-fullbody.png")
    for v in ("front", "profile", "back", "threequarter"):
        _png(look / "turn" / f"jade-turn-{v}.png")
    b = resolve_character_bundle(paths, "jade", max_turn_views=10)
    kinds = [a.kind for a in b.assets]
    assert len(b.assets) == 6
    assert kinds[0] == "identity" and b.assets[0].is_hero is True
    assert kinds[1] == "fullbody"
    assert kinds[2:] == ["turn", "turn", "turn", "turn"]
    assert all(a.is_hero is False for a in b.assets[1:])
    assert {a.view for a in b.assets if a.kind == "turn"} == {"front", "profile", "back", "threequarter"}
