"""ACT performance benchmarks.

Measures Phase 1 creation time (construct + sign + encode) against
the 500µs target from the specification.
"""

import time
import uuid
import statistics

from act import (
    ACTMandate,
    ACTRecord,
    Capability,
    TaskClaim,
    encode_jws,
    decode_jws,
    generate_ed25519_keypair,
    generate_p256_keypair,
    sign,
    verify,
    transition_to_record,
)


def bench_phase1_ed25519(n: int = 10000) -> None:
    """Benchmark Phase 1 creation with Ed25519."""
    priv, pub = generate_ed25519_keypair()

    # Warmup
    for _ in range(100):
        m = ACTMandate(
            alg="EdDSA", kid="k", iss="a", sub="b", aud="b",
            iat=1772064000, exp=1772064900, jti=str(uuid.uuid4()),
            task=TaskClaim(purpose="t"), cap=[Capability(action="x.y")],
        )
        sig = sign(priv, m.signing_input())
        encode_jws(m, sig)

    times = []
    for _ in range(n):
        start = time.perf_counter()
        m = ACTMandate(
            alg="EdDSA", kid="k", iss="a", sub="b", aud="b",
            iat=1772064000, exp=1772064900, jti=str(uuid.uuid4()),
            task=TaskClaim(purpose="benchmark"),
            cap=[Capability(action="read.data")],
        )
        sig = sign(priv, m.signing_input())
        encode_jws(m, sig)
        elapsed = time.perf_counter() - start
        times.append(elapsed * 1_000_000)  # µs

    mean = statistics.mean(times)
    median = statistics.median(times)
    p99 = sorted(times)[int(n * 0.99)]
    print(f"Phase 1 Ed25519 (n={n}):")
    print(f"  Mean:   {mean:.1f} µs")
    print(f"  Median: {median:.1f} µs")
    print(f"  P99:    {p99:.1f} µs")
    print(f"  Target: <= 500 µs {'PASS' if mean <= 500 else 'FAIL'}")
    print()


def bench_phase1_p256(n: int = 5000) -> None:
    """Benchmark Phase 1 creation with P-256."""
    priv, pub = generate_p256_keypair()

    for _ in range(50):
        m = ACTMandate(
            alg="ES256", kid="k", iss="a", sub="b", aud="b",
            iat=1772064000, exp=1772064900, jti=str(uuid.uuid4()),
            task=TaskClaim(purpose="t"), cap=[Capability(action="x.y")],
        )
        sig = sign(priv, m.signing_input())
        encode_jws(m, sig)

    times = []
    for _ in range(n):
        start = time.perf_counter()
        m = ACTMandate(
            alg="ES256", kid="k", iss="a", sub="b", aud="b",
            iat=1772064000, exp=1772064900, jti=str(uuid.uuid4()),
            task=TaskClaim(purpose="benchmark"),
            cap=[Capability(action="read.data")],
        )
        sig = sign(priv, m.signing_input())
        encode_jws(m, sig)
        elapsed = time.perf_counter() - start
        times.append(elapsed * 1_000_000)

    mean = statistics.mean(times)
    median = statistics.median(times)
    p99 = sorted(times)[int(n * 0.99)]
    print(f"Phase 1 ES256 (n={n}):")
    print(f"  Mean:   {mean:.1f} µs")
    print(f"  Median: {median:.1f} µs")
    print(f"  P99:    {p99:.1f} µs")
    print()


def bench_phase2_transition(n: int = 5000) -> None:
    """Benchmark Phase 1 -> Phase 2 transition."""
    iss_priv, _ = generate_ed25519_keypair()
    sub_priv, _ = generate_ed25519_keypair()

    mandate = ACTMandate(
        alg="EdDSA", kid="k", iss="a", sub="b", aud="b",
        iat=1772064000, exp=1772064900, jti=str(uuid.uuid4()),
        task=TaskClaim(purpose="t"), cap=[Capability(action="x.y")],
    )

    # Warmup
    for _ in range(50):
        transition_to_record(
            mandate, sub_kid="sk", sub_private_key=sub_priv,
            exec_act="x.y", pred=[], status="completed",
        )

    times = []
    for _ in range(n):
        start = time.perf_counter()
        transition_to_record(
            mandate, sub_kid="sk", sub_private_key=sub_priv,
            exec_act="x.y", pred=[], status="completed",
        )
        elapsed = time.perf_counter() - start
        times.append(elapsed * 1_000_000)

    mean = statistics.mean(times)
    median = statistics.median(times)
    print(f"Phase 2 Transition (n={n}):")
    print(f"  Mean:   {mean:.1f} µs")
    print(f"  Median: {median:.1f} µs")
    print()


def bench_verify(n: int = 5000) -> None:
    """Benchmark JWS decode + verify."""
    priv, pub = generate_ed25519_keypair()
    m = ACTMandate(
        alg="EdDSA", kid="k", iss="a", sub="b", aud="b",
        iat=1772064000, exp=1772064900, jti=str(uuid.uuid4()),
        task=TaskClaim(purpose="t"), cap=[Capability(action="x.y")],
    )
    sig = sign(priv, m.signing_input())
    compact = encode_jws(m, sig)

    # Warmup
    for _ in range(50):
        _, _, s, si = decode_jws(compact)
        verify(pub, s, si)

    times = []
    for _ in range(n):
        start = time.perf_counter()
        _, _, s, si = decode_jws(compact)
        verify(pub, s, si)
        elapsed = time.perf_counter() - start
        times.append(elapsed * 1_000_000)

    mean = statistics.mean(times)
    median = statistics.median(times)
    print(f"Decode + Verify (n={n}):")
    print(f"  Mean:   {mean:.1f} µs")
    print(f"  Median: {median:.1f} µs")
    print()


if __name__ == "__main__":
    bench_phase1_ed25519()
    bench_phase1_p256()
    bench_phase2_transition()
    bench_verify()
