"""Tests for the AgentIdentity module (DID:key, Ed25519 signing)."""

import pytest
from skytale_sdk.identity import AgentIdentity, resolve_did_web


class TestAgentIdentityGenerate:
    """AgentIdentity.generate() creates valid Ed25519 key pairs."""

    def test_generates_did_key(self):
        identity = AgentIdentity.generate()
        assert identity.did.startswith("did:key:z6Mk")

    def test_public_key_is_32_bytes(self):
        identity = AgentIdentity.generate()
        assert len(identity.public_key) == 32

    def test_private_key_is_32_bytes(self):
        identity = AgentIdentity.generate()
        assert identity.private_key is not None
        assert len(identity.private_key) == 32

    def test_two_identities_are_distinct(self):
        a = AgentIdentity.generate()
        b = AgentIdentity.generate()
        assert a.did != b.did
        assert a.public_key != b.public_key
        assert a.private_key != b.private_key


class TestAgentIdentityFromPrivateKey:
    """AgentIdentity.from_private_key() restores an identity deterministically."""

    def test_roundtrip_private_key(self):
        original = AgentIdentity.generate()
        restored = AgentIdentity.from_private_key(original.private_key)
        assert restored.did == original.did
        assert restored.public_key == original.public_key

    def test_same_private_key_same_did(self):
        original = AgentIdentity.generate()
        r1 = AgentIdentity.from_private_key(original.private_key)
        r2 = AgentIdentity.from_private_key(original.private_key)
        assert r1.did == r2.did


class TestAgentIdentityFromDid:
    """AgentIdentity.from_did() parses did:key and extracts the public key."""

    def test_roundtrip_did(self):
        original = AgentIdentity.generate()
        parsed = AgentIdentity.from_did(original.did)
        assert parsed.public_key == original.public_key
        assert parsed.private_key is None

    def test_invalid_did_raises(self):
        with pytest.raises(ValueError, match="Not a valid did:key"):
            AgentIdentity.from_did("did:web:example.com")

    def test_malformed_did_raises(self):
        with pytest.raises((ValueError, Exception)):
            AgentIdentity.from_did("did:key:invalid")


class TestSignAndVerify:
    """Ed25519 sign/verify cycle."""

    def test_sign_verify_roundtrip(self):
        identity = AgentIdentity.generate()
        message = b"hello, skytale"
        sig = identity.sign(message)
        assert len(sig) == 64
        assert identity.verify(message, sig)

    def test_verify_wrong_message_fails(self):
        identity = AgentIdentity.generate()
        sig = identity.sign(b"original")
        assert not identity.verify(b"tampered", sig)

    def test_verify_wrong_key_fails(self):
        a = AgentIdentity.generate()
        b = AgentIdentity.generate()
        sig = a.sign(b"message")
        assert not b.verify(b"message", sig)

    def test_sign_without_private_key_raises(self):
        identity = AgentIdentity.generate()
        public_only = AgentIdentity.from_did(identity.did)
        with pytest.raises(ValueError, match="no private key"):
            public_only.sign(b"message")

    def test_verify_from_parsed_did(self):
        """Verify works when identity was created from DID (public key only)."""
        signer = AgentIdentity.generate()
        msg = b"cross-agent message"
        sig = signer.sign(msg)

        verifier = AgentIdentity.from_did(signer.did)
        assert verifier.verify(msg, sig)


class TestDidDocument:
    """to_did_document() generates a valid W3C DID Document."""

    def test_document_structure(self):
        identity = AgentIdentity.generate()
        doc = identity.to_did_document()

        assert doc["id"] == identity.did
        assert "https://www.w3.org/ns/did/v1" in doc["@context"]
        assert len(doc["verificationMethod"]) == 1

        vm = doc["verificationMethod"][0]
        assert vm["type"] == "Ed25519VerificationKey2020"
        assert vm["controller"] == identity.did
        assert vm["id"] == f"{identity.did}#key-1"
        assert vm["publicKeyMultibase"].startswith("z")

    def test_authentication_references_key(self):
        identity = AgentIdentity.generate()
        doc = identity.to_did_document()
        assert doc["authentication"] == [f"{identity.did}#key-1"]
        assert doc["assertionMethod"] == [f"{identity.did}#key-1"]
