"""Tests for act.ledger module."""

import pytest

from act.errors import ACTLedgerImmutabilityError
from act.ledger import ACTLedger
from act.token import ACTRecord, Capability, TaskClaim


def make_record(jti, wid=None):
    return ACTRecord(
        alg="EdDSA", kid="k", iss="a", sub="b", aud="b",
        iat=1772064000, exp=1772064900,
        jti=jti, wid=wid,
        task=TaskClaim(purpose="t"),
        cap=[Capability(action="do.thing")],
        exec_act="do.thing", pred=[], exec_ts=1772064100,
        status="completed",
    )


class TestACTLedger:
    def test_append_and_get(self):
        ledger = ACTLedger()
        r = make_record("jti-1")
        seq = ledger.append(r)
        assert seq == 0
        assert ledger.get("jti-1") is r

    def test_sequential_ordering(self):
        ledger = ACTLedger()
        for i in range(5):
            seq = ledger.append(make_record(f"jti-{i}"))
            assert seq == i

    def test_duplicate_rejected(self):
        ledger = ACTLedger()
        ledger.append(make_record("jti-1"))
        with pytest.raises(ACTLedgerImmutabilityError):
            ledger.append(make_record("jti-1"))

    def test_get_missing(self):
        ledger = ACTLedger()
        assert ledger.get("missing") is None

    def test_list_all(self):
        ledger = ACTLedger()
        ledger.append(make_record("a"))
        ledger.append(make_record("b"))
        records = ledger.list()
        assert len(records) == 2

    def test_list_by_wid(self):
        ledger = ACTLedger()
        ledger.append(make_record("a", wid="w1"))
        ledger.append(make_record("b", wid="w2"))
        ledger.append(make_record("c", wid="w1"))
        assert len(ledger.list("w1")) == 2
        assert len(ledger.list("w2")) == 1
        assert len(ledger.list("w3")) == 0

    def test_verify_integrity_empty(self):
        ledger = ACTLedger()
        assert ledger.verify_integrity() is True

    def test_verify_integrity_with_records(self):
        ledger = ACTLedger()
        for i in range(10):
            ledger.append(make_record(f"jti-{i}"))
        assert ledger.verify_integrity() is True

    def test_verify_integrity_tampered(self):
        ledger = ACTLedger()
        ledger.append(make_record("jti-1"))
        ledger.append(make_record("jti-2"))
        # Tamper with chain hash
        ledger._chain_hashes[0] = b"\x00" * 32
        assert ledger.verify_integrity() is False

    def test_len(self):
        ledger = ACTLedger()
        assert len(ledger) == 0
        ledger.append(make_record("a"))
        assert len(ledger) == 1
