import json

from amcs.hashing import event_hash
from amcs.merkle import merkle_root_hex
from amcs.sdk import (
    AMCSClient,
    action_invoke_payload,
    interaction_append_payload,
    memory_upsert_payload,
    policy_update_payload,
)
from amcs.store.sqlite import SQLiteEventStore


def test_sdk_append_verify_end_to_end_with_tamper_detection(tmp_path) -> None:
    store = SQLiteEventStore(str(tmp_path / "events.db"))
    client = AMCSClient(store=store, agent_id="agent-e2e")

    p1 = interaction_append_payload(role="assistant", content="hello")
    p2 = memory_upsert_payload(memory_id="mem-1", content="user likes tea", confidence="0.95")
    p3 = action_invoke_payload(action_name="search", arguments={"q": "amcs"})
    p4 = policy_update_payload(policy_id="pol-1", changes={"allow": ["read"]}, rationale="demo")

    client.append("interaction.append", p1)
    client.append("memory.upsert", p2)
    client.append("action.invoke", p3)
    client.append("policy.update", p4)

    clean = client.verify_chain()
    assert clean.ok is True
    assert clean.checked_events == 4

    with store._conn:
        store._conn.execute(
            "UPDATE events SET event_json = ? WHERE agent_id = ? AND sequence = ?",
            (
                '{"agent_id":"agent-e2e","amcs_version":"AMCS-0.1","event_id":"evt-tampered","event_type":"memory.upsert","payload":{"content":"tampered","confidence":"0.95","memory_id":"mem-1","metadata":{}},"scope":"private","sequence":2,"tags":[],"timestamp":"2026-02-20T00:00:00Z"}',
                "agent-e2e",
                2,
            ),
        )

    tampered = client.verify_chain()
    assert tampered.ok is False
    assert tampered.failed_sequence == 2
    assert tampered.error == "event hash mismatch"


def test_sdk_verify_supports_legacy_rows_missing_sequence_in_event_json(tmp_path) -> None:
    store = SQLiteEventStore(str(tmp_path / "events.db"))
    client = AMCSClient(store=store, agent_id="agent-legacy")

    client.append(
        "interaction.append",
        interaction_append_payload(role="assistant", content="hello"),
    )

    row = store.get_events("agent-legacy", 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-legacy",
                1,
            ),
        )

        # Keep stored hash/root as if canonical envelope included 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-legacy", 1),
        )
        store._conn.execute(
            "UPDATE roots SET memory_root = ? WHERE agent_id = ? AND sequence = ?",
            (merkle_root_hex([hash_with_sequence]), "agent-legacy", 1),
        )

    result = client.verify_chain()
    assert result.ok is True
