import os
import sys
import pytest
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

from flexoentity import FlexOID, FlexoEntity, EntityType, EntityState 


@pytest.fixture
def question():
    """Fresh question entity in draft state."""
    return FlexoEntity("AF", EntityType.QUESTION, "What is Ohm’s law?", EntityState.DRAFT)


# ──────────────────────────────────────────────────────────────────────────────
def test_initial_state(question):
    assert question.state == EntityState.DRAFT
    assert question.flexo_id.version == 1
    assert len(question.flexo_id.signature) == 16  # blake2s digest_size=8 → 16 hex
    assert FlexoEntity.verify_integrity(question)


def test_approval_bumps_version(question):
    question.approve()
    assert question.state == EntityState.APPROVED
    assert question.flexo_id.version == 2


def test_signing_bumps_version(question):
    question.approve()
    v_before = question.flexo_id
    question.sign()
    assert question.state == EntityState.APPROVED_AND_SIGNED
    assert question.flexo_id != v_before

def test_publish_bumps_version(question):
    question.approve()
    question.sign()
    v_before = question.flexo_id.version
    question.publish()
    assert question.state == EntityState.PUBLISHED
    assert question.flexo_id.version == v_before + 1

def test_modify_content_changes_fingerprint(question):
    old_signature = question.flexo_id.signature
    question.modify_content("Rephrased Ohm’s law?")
    assert question.flexo_id.signature != old_signature


def test_no_version_bump_on_draft_edits(question):
    question.modify_content("Draft edit only")
    assert question.flexo_id.version == 1


def test_version_bump_after_edit_and_sign(question):
    question.approve()
    v1 = question.flexo_id
    question.modify_content("Changed content")
    question.sign()
    assert question.flexo_id != v1


def test_integrity_check_passes_and_fails(question):
    question.approve()
    assert FlexoEntity.verify_integrity(question)
    # simulate tampering
    question.text_seed = "Tampered text"
    assert not FlexoEntity.verify_integrity(question)


def test_obsolete_state(question):
    question.approve()
    question.sign()
    question.publish()
    question.obsolete()
    assert question.state == EntityState.OBSOLETE


def test_clone_new_base_resets_lineage(question):
    question.approve()
    question.sign()
    question.publish()
    question.obsolete()
    old_id = question.flexo_id
    question.clone_new_base()
    assert question.flexo_id != old_id
    assert question.state == EntityState.DRAFT
    assert question.flexo_id.version == 1


def test_mass_version_increments_until_obsolete(question):
    question.approve()
    for _ in range(FlexOID.MAX_VERSION - 2):
        question.sign()
    with pytest.raises(RuntimeError, match="mark obsolete"):
        question.sign()
