"""Validate DID WBA document structure generated by the create example."""

from __future__ import annotations

import json
from pathlib import Path
from typing import Any, Dict, Iterable

from anp.authentication import create_did_wba_document

REQUIRED_CONTEXTS = {
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/suites/jws-2020/v1",
    "https://w3id.org/security/suites/secp256k1-2019/v1",
}


def load_or_create_document() -> Dict[str, Any]:
    """Load the document produced by the create example or rebuild it."""
    generated_dir = Path(__file__).resolve().parent / "generated"
    did_path = generated_dir / "did.json"

    if did_path.exists():
        return json.loads(did_path.read_text(encoding="utf-8"))

    did_document, _ = create_did_wba_document(
        hostname="demo.agent-network",
        path_segments=["agents", "demo"],
        agent_description_url="https://demo.agent-network/agents/demo",
    )
    generated_dir.mkdir(parents=True, exist_ok=True)
    did_path.write_text(json.dumps(did_document, indent=2), encoding="utf-8")
    print("did.json not found; regenerated document using create_did_wba_document.")
    return did_document


def assert_contains_all(values: Iterable[str], target: set[str], message: str) -> None:
    """Raise ValueError if target is not covered by values."""
    missing = target.difference(set(values))
    if missing:
        raise ValueError(f"{message}: {sorted(missing)}")


def validate_did_document(did_document: Dict[str, Any]) -> None:
    """Ensure the DID document contains the expected WBA fields."""
    if "id" not in did_document:
        raise ValueError("Missing DID identifier")

    did_value = did_document["id"]
    if not isinstance(did_value, str) or not did_value.startswith("did:wba:"):
        raise ValueError("DID identifier must start with 'did:wba:'")

    contexts = did_document.get("@context", [])
    assert_contains_all(contexts, REQUIRED_CONTEXTS, "Missing @context entries")

    verification_methods = did_document.get("verificationMethod", [])
    if not verification_methods:
        raise ValueError("No verification methods defined")

    primary_method = verification_methods[0]
    expected_method_id = f"{did_value}#key-1"
    if primary_method.get("id") != expected_method_id:
        raise ValueError("Primary verification method id mismatch")

    controller = primary_method.get("controller")
    if controller != did_value:
        raise ValueError("Verification method controller must match DID")

    jwk = primary_method.get("publicKeyJwk", {})
    assert_contains_all(jwk.keys(), {"kty", "crv", "x", "y", "kid"}, "Incomplete publicKeyJwk")
    if jwk.get("crv") != "secp256k1":
        raise ValueError("Unexpected curve for public key")

    authenticators = did_document.get("authentication", [])
    if expected_method_id not in authenticators:
        raise ValueError("Authentication section does not reference key-1")

    services = did_document.get("service", [])
    if services:
        service_endpoint = services[0].get("serviceEndpoint")
        if not service_endpoint or not service_endpoint.startswith("https://"):
            raise ValueError("Service endpoint must use HTTPS")


def main() -> None:
    """Run validation and report the result."""
    did_document = load_or_create_document()

    try:
        validate_did_document(did_document)
    except ValueError as error:
        print(f"DID document validation failed: {error}")
        return

    print("DID document validation succeeded.")


if __name__ == "__main__":
    main()
