use std::{cmp::Ordering, fmt, str::FromStr};
use ed25519_dalek::{Signature, SignatureError, Signer, SigningKey, VerifyingKey};
use rand_core::CryptoRngCore;
use serde::{Deserialize, Serialize};
use crate::store::PublicKeyStore;
#[derive(Clone, Serialize, Deserialize)]
pub struct Author {
    signing_key: SigningKey,
}
impl Author {
    pub fn new<R: CryptoRngCore + ?Sized>(rng: &mut R) -> Self {
        let signing_key = SigningKey::generate(rng);
        Author { signing_key }
    }
    pub fn from_bytes(bytes: &[u8; 32]) -> Self {
        SigningKey::from_bytes(bytes).into()
    }
    pub fn to_bytes(&self) -> [u8; 32] {
        self.signing_key.to_bytes()
    }
    pub fn public_key(&self) -> AuthorPublicKey {
        AuthorPublicKey(self.signing_key.verifying_key())
    }
    pub fn id(&self) -> AuthorId {
        AuthorId::from(self.public_key())
    }
    pub fn sign(&self, msg: &[u8]) -> Signature {
        self.signing_key.sign(msg)
    }
    pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), SignatureError> {
        self.signing_key.verify_strict(msg, signature)
    }
}
#[derive(Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash, derive_more::From)]
pub struct AuthorPublicKey(VerifyingKey);
impl AuthorPublicKey {
    pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), SignatureError> {
        self.0.verify_strict(msg, signature)
    }
    pub fn as_bytes(&self) -> &[u8; 32] {
        self.0.as_bytes()
    }
    pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, SignatureError> {
        Ok(AuthorPublicKey(VerifyingKey::from_bytes(bytes)?))
    }
}
#[derive(Clone, Serialize, Deserialize)]
pub struct NamespaceSecret {
    signing_key: SigningKey,
}
impl NamespaceSecret {
    pub fn new<R: CryptoRngCore + ?Sized>(rng: &mut R) -> Self {
        let signing_key = SigningKey::generate(rng);
        NamespaceSecret { signing_key }
    }
    pub fn from_bytes(bytes: &[u8; 32]) -> Self {
        SigningKey::from_bytes(bytes).into()
    }
    pub fn to_bytes(&self) -> [u8; 32] {
        self.signing_key.to_bytes()
    }
    pub fn public_key(&self) -> NamespacePublicKey {
        NamespacePublicKey(self.signing_key.verifying_key())
    }
    pub fn id(&self) -> NamespaceId {
        NamespaceId::from(self.public_key())
    }
    pub fn sign(&self, msg: &[u8]) -> Signature {
        self.signing_key.sign(msg)
    }
    pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), SignatureError> {
        self.signing_key.verify_strict(msg, signature)
    }
}
#[derive(Default, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, derive_more::From)]
pub struct NamespacePublicKey(VerifyingKey);
impl NamespacePublicKey {
    pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), SignatureError> {
        self.0.verify_strict(msg, signature)
    }
    pub fn as_bytes(&self) -> &[u8; 32] {
        self.0.as_bytes()
    }
    pub fn from_bytes(bytes: &[u8; 32]) -> Result<Self, SignatureError> {
        Ok(NamespacePublicKey(VerifyingKey::from_bytes(bytes)?))
    }
}
impl fmt::Display for Author {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", hex::encode(self.to_bytes()))
    }
}
impl fmt::Display for NamespaceSecret {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", hex::encode(self.to_bytes()))
    }
}
impl fmt::Display for AuthorPublicKey {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", hex::encode(self.as_bytes()))
    }
}
impl fmt::Display for NamespacePublicKey {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", hex::encode(self.as_bytes()))
    }
}
impl fmt::Display for AuthorId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", hex::encode(self.as_bytes()))
    }
}
impl fmt::Display for NamespaceId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", hex::encode(self.as_bytes()))
    }
}
impl fmt::Debug for NamespaceSecret {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Namespace({})", self)
    }
}
impl fmt::Debug for NamespaceId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "NamespaceId({})", hex::encode(self.0))
    }
}
impl fmt::Debug for AuthorId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "AuthorId({})", hex::encode(self.0))
    }
}
impl fmt::Debug for Author {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Author({})", self)
    }
}
impl fmt::Debug for NamespacePublicKey {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "NamespacePublicKey({})", self)
    }
}
impl fmt::Debug for AuthorPublicKey {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "AuthorPublicKey({})", self)
    }
}
fn parse_hex_array(s: &str) -> anyhow::Result<[u8; 32]> {
    let mut bytes = [0u8; 32];
    hex::decode_to_slice(s, &mut bytes)?;
    Ok(bytes)
}
impl FromStr for Author {
    type Err = anyhow::Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Self::from_bytes(&parse_hex_array(s)?))
    }
}
impl FromStr for NamespaceSecret {
    type Err = anyhow::Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Self::from_bytes(&parse_hex_array(s)?))
    }
}
impl FromStr for AuthorPublicKey {
    type Err = anyhow::Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Self::from_bytes(&parse_hex_array(s)?).map_err(Into::into)
    }
}
impl FromStr for NamespacePublicKey {
    type Err = anyhow::Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Self::from_bytes(&parse_hex_array(s)?).map_err(Into::into)
    }
}
impl From<SigningKey> for Author {
    fn from(signing_key: SigningKey) -> Self {
        Self { signing_key }
    }
}
impl From<SigningKey> for NamespaceSecret {
    fn from(signing_key: SigningKey) -> Self {
        Self { signing_key }
    }
}
impl PartialOrd for NamespacePublicKey {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}
impl Ord for NamespacePublicKey {
    fn cmp(&self, other: &Self) -> Ordering {
        self.0.as_bytes().cmp(other.0.as_bytes())
    }
}
impl PartialOrd for AuthorPublicKey {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}
impl Ord for AuthorPublicKey {
    fn cmp(&self, other: &Self) -> Ordering {
        self.0.as_bytes().cmp(other.0.as_bytes())
    }
}
impl From<NamespaceSecret> for NamespacePublicKey {
    fn from(value: NamespaceSecret) -> Self {
        value.public_key()
    }
}
impl From<Author> for AuthorPublicKey {
    fn from(value: Author) -> Self {
        value.public_key()
    }
}
impl From<&NamespaceSecret> for NamespacePublicKey {
    fn from(value: &NamespaceSecret) -> Self {
        value.public_key()
    }
}
impl From<&Author> for AuthorPublicKey {
    fn from(value: &Author) -> Self {
        value.public_key()
    }
}
#[derive(
    Default,
    Clone,
    Copy,
    PartialOrd,
    Ord,
    Eq,
    PartialEq,
    Hash,
    derive_more::From,
    derive_more::Into,
    derive_more::AsRef,
    Serialize,
    Deserialize,
)]
pub struct NamespaceId([u8; 32]);
#[derive(
    Default,
    Clone,
    Copy,
    PartialOrd,
    Ord,
    Eq,
    PartialEq,
    Hash,
    derive_more::From,
    derive_more::Into,
    derive_more::AsRef,
    Serialize,
    Deserialize,
)]
pub struct AuthorId([u8; 32]);
impl AuthorId {
    pub fn to_bytes(&self) -> [u8; 32] {
        self.0
    }
    pub fn as_bytes(&self) -> &[u8; 32] {
        &self.0
    }
    pub fn public_key<S: PublicKeyStore>(
        &self,
        store: &S,
    ) -> Result<AuthorPublicKey, SignatureError> {
        store.author_key(self)
    }
    pub fn into_public_key(&self) -> Result<AuthorPublicKey, SignatureError> {
        AuthorPublicKey::from_bytes(&self.0)
    }
    pub fn fmt_short(&self) -> String {
        hex::encode(self.0).chars().take(10).collect()
    }
}
impl NamespaceId {
    pub fn to_bytes(&self) -> [u8; 32] {
        self.0
    }
    pub fn as_bytes(&self) -> &[u8; 32] {
        &self.0
    }
    pub fn public_key<S: PublicKeyStore>(
        &self,
        store: &S,
    ) -> Result<NamespacePublicKey, SignatureError> {
        store.namespace_key(self)
    }
    pub fn into_public_key(&self) -> Result<NamespacePublicKey, SignatureError> {
        NamespacePublicKey::from_bytes(&self.0)
    }
    pub fn fmt_short(&self) -> String {
        hex::encode(self.0).chars().take(10).collect()
    }
}
impl From<&[u8; 32]> for NamespaceId {
    fn from(value: &[u8; 32]) -> Self {
        Self(*value)
    }
}
impl From<&[u8; 32]> for AuthorId {
    fn from(value: &[u8; 32]) -> Self {
        Self(*value)
    }
}
impl AsRef<[u8]> for NamespaceId {
    fn as_ref(&self) -> &[u8] {
        &self.0
    }
}
impl AsRef<[u8]> for AuthorId {
    fn as_ref(&self) -> &[u8] {
        &self.0
    }
}
impl From<AuthorPublicKey> for AuthorId {
    fn from(value: AuthorPublicKey) -> Self {
        Self(*value.as_bytes())
    }
}
impl From<NamespacePublicKey> for NamespaceId {
    fn from(value: NamespacePublicKey) -> Self {
        Self(*value.as_bytes())
    }
}
impl From<&AuthorPublicKey> for AuthorId {
    fn from(value: &AuthorPublicKey) -> Self {
        Self(*value.as_bytes())
    }
}
impl From<&NamespacePublicKey> for NamespaceId {
    fn from(value: &NamespacePublicKey) -> Self {
        Self(*value.as_bytes())
    }
}
impl From<Author> for AuthorId {
    fn from(value: Author) -> Self {
        value.id()
    }
}
impl From<NamespaceSecret> for NamespaceId {
    fn from(value: NamespaceSecret) -> Self {
        value.id()
    }
}
impl TryFrom<NamespaceId> for NamespacePublicKey {
    type Error = SignatureError;
    fn try_from(value: NamespaceId) -> Result<Self, Self::Error> {
        Self::from_bytes(&value.0)
    }
}
impl TryFrom<AuthorId> for AuthorPublicKey {
    type Error = SignatureError;
    fn try_from(value: AuthorId) -> Result<Self, Self::Error> {
        Self::from_bytes(&value.0)
    }
}
impl FromStr for AuthorId {
    type Err = anyhow::Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        AuthorPublicKey::from_str(s).map(|x| x.into())
    }
}
impl FromStr for NamespaceId {
    type Err = anyhow::Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        NamespacePublicKey::from_str(s).map(|x| x.into())
    }
}