// Copyright (c) Subzero Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

//! Cryptographic primitives and key types used throughout the system

use borsh::{BorshDeserialize, BorshSerialize};
use serde::{Deserialize, Serialize};

/// Size of X25519 private/public keys in bytes.
pub const X25519_KEY_SIZE: usize = 32;

/// Size of TEE user data in bytes.
pub const TEE_USER_DATA_SIZE: usize = 32;

/// Type alias for TEE user data
pub type TeeUserData = [u8; TEE_USER_DATA_SIZE];

/// Strongly typed X25519 public key wrapper used throughout the TEE crates.
///
/// This type provides a type-safe wrapper around X25519 public keys, ensuring
/// proper serialization and preventing misuse of raw byte arrays.
#[derive(
    Clone,
    Copy,
    Debug,
    PartialEq,
    Eq,
    Hash,
    Serialize,
    Deserialize,
    BorshSerialize,
    BorshDeserialize,
)]
pub struct PublicKey([u8; X25519_KEY_SIZE]);

impl PublicKey {
    /// Create a PublicKey from raw bytes
    pub fn from_bytes(bytes: [u8; X25519_KEY_SIZE]) -> Self {
        Self(bytes)
    }

    /// Convert PublicKey to raw bytes
    pub fn to_bytes(self) -> [u8; X25519_KEY_SIZE] {
        self.0
    }

    /// Get a reference to the raw bytes
    pub fn as_bytes(&self) -> &[u8; X25519_KEY_SIZE] {
        &self.0
    }
}

impl From<x25519_dalek::PublicKey> for PublicKey {
    fn from(key: x25519_dalek::PublicKey) -> Self {
        Self(key.to_bytes())
    }
}

impl From<PublicKey> for x25519_dalek::PublicKey {
    fn from(pk: PublicKey) -> Self {
        x25519_dalek::PublicKey::from(pk.0)
    }
}

impl From<&x25519_dalek::StaticSecret> for PublicKey {
    fn from(private_key: &x25519_dalek::StaticSecret) -> Self {
        Self(x25519_dalek::PublicKey::from(private_key).to_bytes())
    }
}

impl AsRef<[u8]> for PublicKey {
    fn as_ref(&self) -> &[u8] {
        &self.0
    }
}

impl AsRef<[u8; X25519_KEY_SIZE]> for PublicKey {
    fn as_ref(&self) -> &[u8; X25519_KEY_SIZE] {
        &self.0
    }
}

impl Default for PublicKey {
    fn default() -> Self {
        Self([0u8; X25519_KEY_SIZE])
    }
}
