import json

from amcs.hashing import event_hash
from amcs.merkle import merkle_root_hex
from amcs.sdk.verify import verify_chain
from amcs.store.sqlite import SQLiteEventStore
from amcs.types import build_event_envelope


def _event(agent_id: str, message: str, ts: str) -> dict:
    return build_event_envelope(
        agent_id=agent_id,
        event_type="interaction.append",
        payload={"message": message},
        timestamp=ts,
    )


def test_verify_chain_passes_for_clean_log(tmp_path) -> None:
    store = SQLiteEventStore(str(tmp_path / "events.db"))
    store.append_event("agent-1", _event("agent-1", "one", "2026-02-19T00:00:01Z"))
    store.append_event("agent-1", _event("agent-1", "two", "2026-02-19T00:00:02Z"))

    result = verify_chain(store, "agent-1")

    assert result.ok is True
    assert result.checked_events == 2
    assert result.error is None


def test_verify_chain_fails_when_event_json_is_tampered(tmp_path) -> None:
    store = SQLiteEventStore(str(tmp_path / "events.db"))
    store.append_event("agent-1", _event("agent-1", "one", "2026-02-19T00:00:01Z"))
    store.append_event("agent-1", _event("agent-1", "two", "2026-02-19T00:00:02Z"))
    store.append_event("agent-1", _event("agent-1", "three", "2026-02-19T00:00:03Z"))

    with store._conn:  # intentional tampering for verification test coverage
        store._conn.execute(
            "UPDATE events SET event_json = ? WHERE agent_id = ? AND sequence = ?",
            (
                '{"agent_id":"agent-1","amcs_version":"AMCS-0.1","event_id":"evt-tampered","event_type":"interaction.append","payload":{"message":"tampered"},"scope":"private","sequence":2,"tags":[],"timestamp":"2026-02-19T00:00:02Z"}',
                "agent-1",
                2,
            ),
        )

    result = verify_chain(store, "agent-1")

    assert result.ok is False
    assert result.failed_sequence == 2
    assert result.error == "event hash mismatch"


def test_verify_chain_legacy_row_without_sequence_uses_db_sequence_fallback(tmp_path) -> None:
    store = SQLiteEventStore(str(tmp_path / "events.db"))
    store.append_event("agent-1", _event("agent-1", "one", "2026-02-19T00:00:01Z"))

    row = store.get_events("agent-1", from_seq=1, to_seq=1)[0]
    legacy_event = dict(row["event"])
    del legacy_event["sequence"]

    with store._conn:
        store._conn.execute(
            "UPDATE events SET event_json = ? WHERE agent_id = ? AND sequence = ?",
            (
                json.dumps(legacy_event, sort_keys=True, separators=(",", ":"), ensure_ascii=False),
                "agent-1",
                1,
            ),
        )

        # Preserve hashes/roots as if they were computed from canonical event including sequence.
        hash_with_sequence = event_hash({**legacy_event, "sequence": 1})
        store._conn.execute(
            "UPDATE events SET event_hash = ? WHERE agent_id = ? AND sequence = ?",
            (hash_with_sequence, "agent-1", 1),
        )
        store._conn.execute(
            "UPDATE roots SET memory_root = ? WHERE agent_id = ? AND sequence = ?",
            (merkle_root_hex([hash_with_sequence]), "agent-1", 1),
        )

    result = verify_chain(store, "agent-1")

    assert result.ok is True
