from __future__ import annotations

from synaptopus.examples import (
    ParityPressureState,
    XorDemoState,
    build_parity_pressure_demo,
    build_xor_novelty_demo,
)
from synaptopus.reporting import summarize_sequence_run
from synaptopus.runtime import run_until_acceptance_count


def test_xor_novelty_demo_accepts_xor_positive_patterns() -> None:
    system = build_xor_novelty_demo()

    record = run_until_acceptance_count(
        system,
        XorDemoState(),
        accepted_count=2,
        max_attempts_per_accept=4,
    )

    assert tuple(step.candidate for step in record.accepted) == ((0, 1), (1, 0))
    assert record.final_state.accepted == ((0, 1), (1, 0))


def test_xor_novelty_demo_produces_reportable_sequence() -> None:
    system = build_xor_novelty_demo()
    record = run_until_acceptance_count(
        system,
        XorDemoState(),
        accepted_count=2,
        max_attempts_per_accept=4,
    )

    report = summarize_sequence_run(
        record,
        sequence_getter=lambda current: [left * 2 + right for left, right in current.final_state.accepted],
        alphabet_size=4,
        parameters={"example": "xor_novelty"},
    )

    assert report.parameters["example"] == "xor_novelty"
    assert report.accepted_count == 2
    assert report.sequence_analysis["item_count"] == 2


def test_parity_pressure_demo_exhibits_retries_and_repeated_acceptance() -> None:
    system = build_parity_pressure_demo()
    record = run_until_acceptance_count(
        system,
        ParityPressureState(),
        accepted_count=4,
        max_attempts_per_accept=10,
    )

    accepted_candidates = tuple(step.candidate for step in record.accepted)

    assert len(accepted_candidates) == 4
    assert record.attempt_count > record.accepted_count
    assert all(sum(candidate) % 2 == 1 for candidate in accepted_candidates)
    assert any(
        (step.metadata is not None and step.metadata.category.delta_vigilance)
        for step in record.attempts
        if not step.accepted
    )
