"""SRP-6a interop verification.

Uses srptools to perform a complete SRP handshake with fixed inputs,
then prints all intermediate hex values. The TypeScript SRP client
(frontend/src/lib/crypto/srp.ts) can be verified against these
known-good values to catch encoding mismatches.

Run standalone:
    cd backend && python -m tests.test_srp_interop

Or via pytest:
    cd backend && python -m pytest tests/test_srp_interop.py -v
"""

from srptools import SRPContext, SRPClientSession, SRPServerSession
from srptools.constants import PRIME_2048, PRIME_2048_GEN


# Fixed test inputs
EMAIL = "test@example.com"
PASSWORD = "test-password"


def test_srp_roundtrip():
    """Verify srptools produces a successful handshake end-to-end.

    This test ensures the server-side library completes a full SRP
    handshake without errors. The printed intermediate values serve as
    reference data for the TypeScript client interop test.
    """
    # Step 1: Registration -- compute salt + verifier (needs password in context)
    context = SRPContext(EMAIL, password=PASSWORD, prime=PRIME_2048, generator=PRIME_2048_GEN)
    username, verifier, salt = context.get_user_data_triplet()

    print(f"\n--- SRP Interop Reference Values ---")
    print(f"email (I): {EMAIL}")
    print(f"salt (s):  {salt}")
    print(f"verifier (v): {verifier[:64]}...  (len={len(verifier)})")

    # Step 2: Server init -- generate B (server only needs verifier, no password)
    server_context = SRPContext(EMAIL, prime=PRIME_2048, generator=PRIME_2048_GEN)
    server_session = SRPServerSession(server_context, verifier)
    server_public = server_session.public

    print(f"server_public (B): {server_public[:64]}...  (len={len(server_public)})")

    # Step 3: Client init -- generate A (client needs password for proof)
    client_context = SRPContext(EMAIL, password=PASSWORD, prime=PRIME_2048, generator=PRIME_2048_GEN)
    client_session = SRPClientSession(client_context)
    client_public = client_session.public

    print(f"client_public (A): {client_public[:64]}...  (len={len(client_public)})")

    # Step 4: Client processes B
    client_session.process(server_public, salt)

    # Step 5: Server processes A
    server_session.process(client_public, salt)

    # Step 6: Client generates proof M1
    client_proof = client_session.key_proof

    print(f"client_proof (M1): {client_proof}")

    # Step 7: Server verifies M1 and generates M2
    server_session.verify_proof(client_proof)
    server_proof = server_session.key_proof_hash

    print(f"server_proof (M2): {server_proof}")

    # Step 8: Client verifies M2
    client_session.verify_proof(server_proof)

    # Step 9: Verify session keys match
    assert client_session.key == server_session.key, (
        f"Session key mismatch: client={client_session.key[:32]}... "
        f"server={server_session.key[:32]}..."
    )

    print(f"session_key (K): {client_session.key[:64]}...  (len={len(client_session.key)})")
    print(f"--- Handshake PASSED ---\n")


def test_srp_bad_proof_rejected():
    """Verify that an incorrect M1 proof is rejected by the server."""
    context = SRPContext(EMAIL, password=PASSWORD, prime=PRIME_2048, generator=PRIME_2048_GEN)
    _, verifier, salt = context.get_user_data_triplet()

    server_context = SRPContext(EMAIL, prime=PRIME_2048, generator=PRIME_2048_GEN)
    server_session = SRPServerSession(server_context, verifier)

    client_context = SRPContext(EMAIL, password=PASSWORD, prime=PRIME_2048, generator=PRIME_2048_GEN)
    client_session = SRPClientSession(client_context)

    client_session.process(server_session.public, salt)
    server_session.process(client_session.public, salt)

    # Tamper with proof
    bad_proof = "00" * 32

    try:
        server_session.verify_proof(bad_proof)
        assert False, "Server should have rejected bad proof"
    except Exception:
        pass  # Expected: bad proof rejected


def test_srp_deterministic_verifier():
    """Verify that the same salt + identity produce consistent verifiers."""
    context1 = SRPContext(EMAIL, password=PASSWORD, prime=PRIME_2048, generator=PRIME_2048_GEN)
    _, v1, s1 = context1.get_user_data_triplet()

    # Same email + password, new context
    context2 = SRPContext(EMAIL, password=PASSWORD, prime=PRIME_2048, generator=PRIME_2048_GEN)
    _, v2, s2 = context2.get_user_data_triplet()

    # srptools generates random salt each time, so verifiers will differ.
    # But the output format is consistent.
    assert len(v1) > 0
    assert len(v2) > 0
    assert len(s1) == len(s2), "Salt lengths should be consistent"


if __name__ == "__main__":
    test_srp_roundtrip()
    test_srp_bad_proof_rejected()
    test_srp_deterministic_verifier()
    print("All SRP interop tests passed.")
