"""Tests for Ed25519 key management — validates cross-compatibility with the Node.js SDK."""

from __future__ import annotations

import base64
import json
import tempfile
from pathlib import Path

from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat

from beeos_bridge_client.keys import (
    fingerprint,
    generate_key_pair,
    load_key_pair,
    public_key_from_private,
    sign,
)


def test_generate_key_pair_lengths():
    kp = generate_key_pair()
    assert len(kp.public_key) == 32
    assert len(kp.private_key) == 32


def test_generate_and_save():
    with tempfile.TemporaryDirectory() as d:
        path = Path(d) / "sub" / "key.json"
        kp = generate_key_pair(save_to=path)

        assert path.exists()
        data = json.loads(path.read_text())
        assert base64.b64decode(data["publicKey"]) == kp.public_key
        assert base64.b64decode(data["privateKey"]) == kp.private_key


def test_load_json_format():
    with tempfile.TemporaryDirectory() as d:
        path = Path(d) / "key.json"
        original = generate_key_pair(save_to=path)
        loaded = load_key_pair(path)
        assert loaded.public_key == original.public_key
        assert loaded.private_key == original.private_key


def test_load_raw_seed_format():
    """Simulate the K8s secret mount: raw base64 seed only."""
    kp = generate_key_pair()
    with tempfile.TemporaryDirectory() as d:
        path = Path(d) / "seed"
        path.write_text(base64.b64encode(kp.private_key).decode())

        loaded = load_key_pair(path)
        assert loaded.private_key == kp.private_key
        assert loaded.public_key == kp.public_key


def test_load_creates_if_missing():
    with tempfile.TemporaryDirectory() as d:
        path = Path(d) / "new.json"
        kp = load_key_pair(path)
        assert path.exists()
        assert len(kp.public_key) == 32


def test_fingerprint_is_sha256_hex():
    kp = generate_key_pair()
    fp = fingerprint(kp.public_key)
    assert len(fp) == 64
    assert all(c in "0123456789abcdef" for c in fp)


def test_sign_and_verify():
    kp = generate_key_pair()
    msg = "acp|abc123|1700000000|uuid-nonce"
    sig = sign(msg, kp.private_key)
    assert len(sig) == 64

    pub_obj = Ed25519PublicKey.from_public_bytes(kp.public_key)
    pub_obj.verify(sig, msg.encode())  # raises on failure


def test_public_key_from_private():
    kp = generate_key_pair()
    derived = public_key_from_private(kp.private_key)
    assert derived == kp.public_key


def test_sign_format_matches_bridge_protocol():
    """Ensure the signed message format matches: service|pub_b64|timestamp|nonce"""
    kp = generate_key_pair()
    pub_b64 = base64.b64encode(kp.public_key).decode()
    timestamp = 1700000000
    nonce = "test-nonce-uuid"
    service = "acp"

    msg = f"{service}|{pub_b64}|{timestamp}|{nonce}"
    sig = sign(msg, kp.private_key)

    pub_obj = Ed25519PublicKey.from_public_bytes(kp.public_key)
    pub_obj.verify(sig, msg.encode())
