"""Tests for BOB Passport verification."""

from datetime import datetime, timedelta, timezone

from bob.passport import verify_passport


def _make_passport(**overrides):
    now = datetime.now(timezone.utc)
    expiry = now + timedelta(days=30)
    base = {
        "@context": ["https://www.w3.org/ns/credentials/v2", "https://bobscore.ai/context/v1"],
        "id": "did:bob:passport:agent-1:12345",
        "type": ["VerifiableCredential", "BoBAgentPassport"],
        "issuer": "did:web:bobscore.ai",
        "validFrom": now.isoformat(),
        "validUntil": expiry.isoformat(),
        "credentialSubject": {
            "id": "did:bob:agent:agent-1",
            "version": "2.0",
            "subject": {
                "agent_id": "agent-1",
                "key": {"kid": "ed-1", "alg": "Ed25519", "public_key_jwk": {"kty": "OKP", "crv": "Ed25519", "x": "abc"}},
            },
            "backing": {"operator_id": "op-1", "kyc_verified": False},
            "trust": {
                "score": 500,
                "tier": "Established",
                "tier_color": "#8c5cff",
                "proven_rails": ["lightning", "evm_wallet"],
                "payment_history_sources": [],
                "signals": {},
            },
        },
        "proof": {
            "type": "EcdsaSecp256k1Signature2024",
            "created": now.isoformat(),
            "verification_method": "did:web:bobscore.ai#key-1",
            "signature": "0xdeadbeef",
        },
    }
    base.update(overrides)
    return base


def test_valid_passport():
    result = verify_passport(_make_passport())
    assert result["valid"] is True
    assert result["agent_id"] == "agent-1"
    assert result["score"] == 500
    assert result["tier"] == "Established"


def test_expired():
    p = _make_passport(validUntil=(datetime.now(timezone.utc) - timedelta(hours=1)).isoformat())
    result = verify_passport(p)
    assert result["valid"] is False
    assert "expired" in result["reason"]


def test_min_score_fail():
    result = verify_passport(_make_passport(), min_score=600)
    assert result["valid"] is False
    assert "below minimum 600" in result["reason"]


def test_min_score_pass():
    result = verify_passport(_make_passport(), min_score=400)
    assert result["valid"] is True


def test_min_tier_fail():
    result = verify_passport(_make_passport(), min_tier="Trusted")
    assert result["valid"] is False
    assert "Trusted" in result["reason"]


def test_min_tier_pass():
    result = verify_passport(_make_passport(), min_tier="Established")
    assert result["valid"] is True


def test_require_rails_fail():
    result = verify_passport(_make_passport(), require_rails=["solana"])
    assert result["valid"] is False
    assert "solana" in result["reason"]


def test_require_rails_pass():
    result = verify_passport(_make_passport(), require_rails=["lightning"])
    assert result["valid"] is True


def test_invalid_structure():
    result = verify_passport({})
    assert result["valid"] is False
    assert "structure" in result["reason"]


def test_unknown_issuer():
    result = verify_passport(_make_passport(issuer="did:web:evil.com"))
    assert result["valid"] is False
    assert "untrusted issuer" in result["reason"]


def test_max_age():
    old = _make_passport(validFrom=(datetime.now(timezone.utc) - timedelta(hours=2)).isoformat())
    result = verify_passport(old, max_age_seconds=3600)
    assert result["valid"] is False
    assert "too old" in result["reason"]


# ---------------------------------------------------------------------------
# JWT tests
# ---------------------------------------------------------------------------

import base64
import json as json_mod

from bob.passport import decode_passport_jwt, verify_passport_jwt


def _make_jwt(**passport_overrides):
    passport = _make_passport(**passport_overrides)
    header = {"alg": "ES256K", "typ": "JWT", "kid": "did:web:bobscore.ai#key-1"}
    payload = {
        "iss": passport["issuer"],
        "sub": passport["credentialSubject"]["id"],
        "iat": int(datetime.now(timezone.utc).timestamp()),
        "exp": int((datetime.now(timezone.utc) + timedelta(days=30)).timestamp()),
        "jti": passport["id"],
        "vc": passport,
    }

    def b64url(obj):
        return base64.urlsafe_b64encode(json_mod.dumps(obj).encode()).rstrip(b"=").decode()

    return b64url(header) + "." + b64url(payload) + "." + b64url({"fake": "sig"})


def test_decode_passport_jwt():
    token = _make_jwt()
    result = decode_passport_jwt(token)
    assert result["header"]["alg"] == "ES256K"
    assert result["passport"]["credentialSubject"]["subject"]["agent_id"] == "agent-1"


def test_decode_passport_jwt_invalid():
    import pytest
    with pytest.raises(ValueError, match="3 dot-separated"):
        decode_passport_jwt("not-a-jwt")


def test_decode_passport_jwt_wrong_alg():
    import pytest
    header = base64.urlsafe_b64encode(json_mod.dumps({"alg": "RS256"}).encode()).rstrip(b"=").decode()
    payload = base64.urlsafe_b64encode(json_mod.dumps({"vc": {}}).encode()).rstrip(b"=").decode()
    with pytest.raises(ValueError, match="Unsupported"):
        decode_passport_jwt(header + "." + payload + ".sig")


def test_verify_passport_jwt():
    token = _make_jwt()
    result = verify_passport_jwt(token, min_score=400)
    assert result["valid"] is True
    assert result["score"] == 500


def test_verify_passport_jwt_min_score_fail():
    token = _make_jwt()
    result = verify_passport_jwt(token, min_score=600)
    assert result["valid"] is False
    assert "below minimum" in result["reason"]


def test_verify_passport_jwt_invalid():
    result = verify_passport_jwt("garbage")
    assert result["valid"] is False
