from __future__ import annotations

from dataclasses import dataclass

from synaptopus.reporting import summarize_execution, summarize_sequence_run
from synaptopus.runtime import StepTrace, run_until_acceptance_count


@dataclass(frozen=True)
class SequenceState:
    accepted: tuple[int, ...] = ()
    attempts: int = 0


class EvenAcceptanceSystem:
    def step(self, state: SequenceState) -> StepTrace[SequenceState, int, None]:
        candidate = state.attempts + 1
        accepted = candidate % 2 == 0
        next_state = SequenceState(
            accepted=state.accepted + ((candidate,) if accepted else ()),
            attempts=state.attempts + 1,
        )
        return StepTrace(
            previous_state=state,
            next_state=next_state,
            candidate=candidate,
            accepted=accepted,
            elapsed_seconds=0.0,
            metadata=None,
        )


def test_summarize_execution_reports_attempt_rates() -> None:
    record = run_until_acceptance_count(
        EvenAcceptanceSystem(),
        SequenceState(),
        accepted_count=3,
        max_attempts_per_accept=4,
    )

    report = summarize_execution(record, parameters={"mode": "demo"})

    assert report.parameters["mode"] == "demo"
    assert report.accepted_count == 3
    assert report.attempt_count == 6
    assert report.average_attempts_per_accept == 2.0


def test_summarize_sequence_run_includes_entropy_metrics() -> None:
    record = run_until_acceptance_count(
        EvenAcceptanceSystem(),
        SequenceState(),
        accepted_count=3,
        max_attempts_per_accept=4,
    )

    report = summarize_sequence_run(
        record,
        sequence_getter=lambda current: current.final_state.accepted,
        alphabet_size=8,
    )

    assert report.sequence_analysis["item_count"] == 3
    assert "unigram_entropy_bits" in report.sequence_analysis
