"""
Cross-SDK interoperability helpers for Python.

When run with 'produce': generates keys, signs a message, writes artifacts to
INTEROP_DIR. When run with 'verify': reads artifacts from all SDKs in
INTEROP_DIR and verifies them.
"""
import json
import os
import sys
from pathlib import Path

from dataclasses import asdict

from hallpass_sdk import (
    generate_agent_key_material,
    create_message_proof_bundle,
    verify_message_proof_bundle,
    create_agent_challenge_response,
    create_delegation_jwt,
    sign_compact_jwt,
    verify_compact_jwt,
    fingerprint_public_jwk,
)
from hallpass_sdk.messages import MessageProofBundle
import pytest

INTEROP_DIR = os.environ.get("INTEROP_DIR")
if not INTEROP_DIR:
    try:
        pytest.skip("Set INTEROP_DIR to run interop tests", allow_module_level=True)
    except ImportError:
        print("Set INTEROP_DIR to run interop tests", file=sys.stderr)
        sys.exit(1)

SDK_NAME = "python"
USERNAME = "interop-test-user"
AUTHOR_LABEL = "interop-agent"
MESSAGE_BODY = "Cross-SDK integration test message"
CHALLENGE_NONCE = "interop-challenge-nonce-42"


def produce():
    sdk_dir = Path(INTEROP_DIR) / SDK_NAME
    sdk_dir.mkdir(parents=True, exist_ok=True)

    keys = generate_agent_key_material()

    (sdk_dir / "keys.json").write_text(json.dumps({
        "did": keys.did,
        "verification_method": keys.verification_method,
        "public_jwk": keys.public_jwk,
        "key_fingerprint": keys.key_fingerprint,
    }, indent=2))

    bundle = create_message_proof_bundle(
        principal_username=USERNAME,
        author_label=AUTHOR_LABEL,
        body=MESSAGE_BODY,
        key_material=keys,
    )
    (sdk_dir / "bundle.json").write_text(json.dumps(asdict(bundle), indent=2))

    challenge_jwt = create_agent_challenge_response(
        challenge=CHALLENGE_NONCE,
        key_material=keys,
    )
    (sdk_dir / "challenge.json").write_text(json.dumps({
        "challenge_jwt": challenge_jwt,
        "challenge": CHALLENGE_NONCE,
    }, indent=2))

    import time
    now = int(time.time())
    delegation_payload = {
        "sub": USERNAME,
        "user_id": "u-interop",
        "agent_id": "a-interop",
        "agent_did": keys.did,
        "agent_verification_method": keys.verification_method,
        "agent_key_fingerprint": keys.key_fingerprint,
        "display_name": AUTHOR_LABEL,
        "attestation_ids": ["att-interop-1"],
        "iat": now,
        "nbf": now,
        "exp": now + 3600,
        "jti": "del-interop-py",
        "typ": "hallpass-profile-authorization",
    }
    delegation_jwt = create_delegation_jwt(delegation_payload, keys.private_jwk)
    (sdk_dir / "delegation.json").write_text(json.dumps({
        "delegation_jwt": delegation_jwt,
        "payload": delegation_payload,
    }, indent=2))

    print(f"[{SDK_NAME}] Produced artifacts in {sdk_dir}")


def verify():
    interop = Path(INTEROP_DIR)
    passed = 0
    failed = 0

    for sdk_dir in sorted(interop.iterdir()):
        if not sdk_dir.is_dir():
            continue
        sdk = sdk_dir.name

        # Verify message bundle
        try:
            bundle_data = json.loads((sdk_dir / "bundle.json").read_text())
            bundle_obj = MessageProofBundle(**bundle_data)
            result = verify_message_proof_bundle(bundle_obj)
            assert result.signature_valid, "signature_valid is false"
            assert result.key_matches, "key_matches is false"
            assert result.message["body"] == MESSAGE_BODY, f"body mismatch: {result.message['body']}"
            print(f"[{SDK_NAME}] ✓ Verified bundle from {sdk}")
            passed += 1
        except Exception as e:
            print(f"[{SDK_NAME}] ✗ Failed to verify bundle from {sdk}: {e}", file=sys.stderr)
            failed += 1

        # Verify challenge JWT
        try:
            challenge_data = json.loads((sdk_dir / "challenge.json").read_text())
            keys_data = json.loads((sdk_dir / "keys.json").read_text())
            result = verify_compact_jwt(challenge_data["challenge_jwt"], keys_data["public_jwk"])
            assert result.valid, "challenge JWT signature invalid"
            assert result.payload["challenge"] == CHALLENGE_NONCE, "challenge nonce mismatch"
            print(f"[{SDK_NAME}] ✓ Verified challenge from {sdk}")
            passed += 1
        except Exception as e:
            print(f"[{SDK_NAME}] ✗ Failed to verify challenge from {sdk}: {e}", file=sys.stderr)
            failed += 1

        # Verify delegation JWT
        try:
            deleg_data = json.loads((sdk_dir / "delegation.json").read_text())
            keys_data = json.loads((sdk_dir / "keys.json").read_text())
            result = verify_compact_jwt(deleg_data["delegation_jwt"], keys_data["public_jwk"])
            assert result.valid, "delegation JWT signature invalid"
            assert result.payload["typ"] == "hallpass-profile-authorization", "typ mismatch"
            print(f"[{SDK_NAME}] ✓ Verified delegation from {sdk}")
            passed += 1
        except Exception as e:
            print(f"[{SDK_NAME}] ✗ Failed to verify delegation from {sdk}: {e}", file=sys.stderr)
            failed += 1

        # Cross-check key fingerprint
        try:
            keys_data = json.loads((sdk_dir / "keys.json").read_text())
            computed = fingerprint_public_jwk(keys_data["public_jwk"])
            assert computed == keys_data["key_fingerprint"], \
                f"fingerprint mismatch: {computed} != {keys_data['key_fingerprint']}"
            print(f"[{SDK_NAME}] ✓ Fingerprint matches for {sdk}")
            passed += 1
        except Exception as e:
            print(f"[{SDK_NAME}] ✗ Fingerprint mismatch for {sdk}: {e}", file=sys.stderr)
            failed += 1

    print(f"\n[{SDK_NAME}] Results: {passed} passed, {failed} failed")
    if failed > 0:
        sys.exit(1)


if __name__ == "__main__":
    mode = sys.argv[1] if len(sys.argv) > 1 else None
    if mode == "produce":
        produce()
    elif mode == "verify":
        verify()
    else:
        print("Usage: python test_interop.py [produce|verify]", file=sys.stderr)
        sys.exit(1)
