"""Ed25519 keypair management for device identity."""

from __future__ import annotations

import logging
import os
from pathlib import Path

logger = logging.getLogger(__name__)


class DeviceIdentity:
    """Manages device keypair and short device identifier."""

    def __init__(self, vault_dir: Path):
        self._vault_dir = Path(vault_dir)
        self._key_path = self._vault_dir / ".device_key"
        self._private_key = None
        self._public_key = None

    def get_or_create(self) -> "DeviceIdentity":
        """Load existing keypair or generate a new one."""
        try:
            from cryptography.hazmat.primitives import serialization
            from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
        except Exception as exc:  # pragma: no cover - optional dependency
            raise RuntimeError("cryptography is required for federation identity") from exc

        if self._key_path.exists():
            key_data = self._key_path.read_bytes()
            self._private_key = serialization.load_pem_private_key(key_data, password=None)
            self._public_key = self._private_key.public_key()
            return self

        self._private_key = Ed25519PrivateKey.generate()
        self._public_key = self._private_key.public_key()

        pem = self._private_key.private_bytes(
            serialization.Encoding.PEM,
            serialization.PrivateFormat.PKCS8,
            serialization.NoEncryption(),
        )
        self._key_path.parent.mkdir(parents=True, exist_ok=True)
        self._key_path.write_bytes(pem)
        try:
            os.chmod(self._key_path, 0o600)
        except Exception as exc:
            logger.debug("Unable to chmod identity key %s: %s", self._key_path, exc)
        return self

    @property
    def private_key(self):
        return self._private_key

    @property
    def public_key(self):
        return self._public_key

    @property
    def public_key_hex(self) -> str:
        if self._public_key is None:
            return ""
        from cryptography.hazmat.primitives import serialization

        raw = self._public_key.public_bytes(
            serialization.Encoding.Raw,
            serialization.PublicFormat.Raw,
        )
        return raw.hex()

    @property
    def device_id(self) -> str:
        return self.public_key_hex[:16]
