"""ADR-0021 non-hardening invariant tests.

The Epistemic Grade Policy commits to:

1. `epistemic_status` is a position in the revision graph, not a trust
   tier.
2. No reviewed claim, relation, or proposition-graph edge ever becomes
   unrevisable — no `final`, `frozen`, `axiom`, or `permanent` flag may
   exist or be added on the runtime data model.
3. Coherence is the only admission signal — source-trust labels must not
   be part of the schema.

These tests are the structural checks behind those commitments.  They
are intentionally simple and read like contract assertions, not
behaviour tests.
"""

from __future__ import annotations

import dataclasses

from teaching import EpistemicStatus, PackMutationProposal, ReviewedTeachingExample
from teaching.correction import CorrectionCandidate
from teaching.review import ReviewOutcome
from teaching.source import ProposalSource


_FORBIDDEN_HARDENING_NAMES: frozenset[str] = frozenset({
    "final",
    "frozen",
    "axiom",
    "permanent",
    "immutable_truth",
    "sealed",
})

# Source-trust tier names that ADR-0021 §3 forbids in the schema.
_FORBIDDEN_TRUST_TIER_NAMES: frozenset[str] = frozenset({
    "peer_consensus",
    "outsider_empirical",
    "established",
    "unauthoritative",
    "credentialed",
    "source_trust",
    "authority",
    "trust_tier",
})


def _field_names(cls: type) -> set[str]:
    return {f.name for f in dataclasses.fields(cls)}


def _enum_value_strings(enum_cls) -> set[str]:
    return {member.value for member in enum_cls}


def test_pack_mutation_proposal_has_no_hardening_flag():
    """PackMutationProposal must not expose any name implying permanence."""
    names = _field_names(PackMutationProposal)
    forbidden = names & _FORBIDDEN_HARDENING_NAMES
    assert forbidden == set(), (
        f"PackMutationProposal exposes hardening flag(s) {forbidden}; "
        "ADR-0021 §2 forbids non-revisable state on the runtime data model."
    )


def test_reviewed_teaching_example_has_no_hardening_flag():
    """ReviewedTeachingExample must not expose any name implying permanence."""
    names = _field_names(ReviewedTeachingExample)
    forbidden = names & _FORBIDDEN_HARDENING_NAMES
    assert forbidden == set(), (
        f"ReviewedTeachingExample exposes hardening flag(s) {forbidden}; "
        "ADR-0021 §2 forbids non-revisable state on the runtime data model."
    )


def test_epistemic_status_enum_carries_no_trust_tier_names():
    """EpistemicStatus must describe revision-graph position, not source trust."""
    values = _enum_value_strings(EpistemicStatus)
    forbidden = values & _FORBIDDEN_TRUST_TIER_NAMES
    assert forbidden == set(), (
        f"EpistemicStatus enum contains source-trust tier value(s) {forbidden}; "
        "ADR-0021 §3 forbids credentialing the schema."
    )


def test_epistemic_status_enum_has_exactly_the_four_positions():
    """ADR-0021 §1 names the enum members precisely; no silent additions."""
    assert _enum_value_strings(EpistemicStatus) == {
        "coherent",
        "contested",
        "speculative",
        "falsified",
    }


def test_proposal_default_is_speculative():
    """ADR-0021 §Schema impact: proposals start SPECULATIVE; promotion is
    a separate, review-mediated transition."""
    proposal = PackMutationProposal(
        proposal_id="x",
        candidate_id="y",
        subject="z",
        correction_text="a knows b",
        prior_surface="",
        source=ProposalSource.operator(emitted_at_revision="test"),
    )
    assert proposal.epistemic_status is EpistemicStatus.SPECULATIVE


def test_proposal_with_status_returns_new_immutable_proposal():
    """Immutable update — the original is never mutated."""
    original = PackMutationProposal(
        proposal_id="x",
        candidate_id="y",
        subject="z",
        correction_text="a knows b",
        prior_surface="",
        source=ProposalSource.operator(emitted_at_revision="test"),
    )
    promoted = original.with_status(EpistemicStatus.COHERENT)

    assert promoted.epistemic_status is EpistemicStatus.COHERENT
    assert original.epistemic_status is EpistemicStatus.SPECULATIVE
    assert promoted is not original


def test_reviewed_example_default_is_speculative_for_accepted_outcome():
    """Acceptance is orthogonal to coherence ratification per ADR-0021
    §Schema impact: 'Accepting a proposal is not the same as ratifying
    it as COHERENT.'"""
    from generate.intent import DialogueIntent, IntentTag

    intent = DialogueIntent(tag=IntentTag.DEFINITION, subject="a")
    candidate = CorrectionCandidate(
        candidate_id="c1",
        intent=intent,
        correction_text="a is b",
        prior_surface="",
        prior_turn=0,
    )
    from teaching import review_correction

    reviewed = review_correction(candidate)
    assert reviewed.outcome is ReviewOutcome.ACCEPTED
    assert reviewed.epistemic_status is EpistemicStatus.SPECULATIVE
