//! Key management domain logic — KeyPackage and hybrid key operations.

use std::sync::Arc;

use sha2::{Digest, Sha256};

use crate::storage::Store;

use super::types::*;

const MAX_KEYPACKAGE_BYTES: usize = 1024 * 1024; // 1 MB

/// Domain service for MLS KeyPackage and hybrid (PQ) key management.
pub struct KeyService {
    pub store: Arc<dyn Store>,
}

impl KeyService {
    pub fn upload_key_package(
        &self,
        req: UploadKeyPackageReq,
        _auth: &CallerAuth,
    ) -> Result<UploadKeyPackageResp, DomainError> {
        if req.identity_key.len() != 32 {
            return Err(DomainError::InvalidIdentityKey(req.identity_key.len()));
        }
        if req.package.is_empty() {
            return Err(DomainError::EmptyPackage);
        }
        if req.package.len() > MAX_KEYPACKAGE_BYTES {
            return Err(DomainError::PackageTooLarge(req.package.len()));
        }

        let fingerprint: Vec<u8> = Sha256::digest(&req.package).to_vec();
        self.store
            .upload_key_package(&req.identity_key, req.package)?;

        Ok(UploadKeyPackageResp { fingerprint })
    }

    pub fn fetch_key_package(
        &self,
        req: FetchKeyPackageReq,
        _auth: &CallerAuth,
    ) -> Result<FetchKeyPackageResp, DomainError> {
        let package = self.store.fetch_key_package(&req.identity_key)?;
        Ok(FetchKeyPackageResp {
            package: package.unwrap_or_default(),
        })
    }

    pub fn upload_hybrid_key(
        &self,
        req: UploadHybridKeyReq,
        _auth: &CallerAuth,
    ) -> Result<(), DomainError> {
        if req.identity_key.len() != 32 {
            return Err(DomainError::InvalidIdentityKey(req.identity_key.len()));
        }
        if req.hybrid_public_key.is_empty() {
            return Err(DomainError::EmptyHybridKey);
        }

        self.store
            .upload_hybrid_key(&req.identity_key, req.hybrid_public_key)?;
        Ok(())
    }

    pub fn fetch_hybrid_key(
        &self,
        req: FetchHybridKeyReq,
        _auth: &CallerAuth,
    ) -> Result<FetchHybridKeyResp, DomainError> {
        let hybrid_public_key = self
            .store
            .fetch_hybrid_key(&req.identity_key)?
            .unwrap_or_default();
        Ok(FetchHybridKeyResp { hybrid_public_key })
    }

    pub fn fetch_hybrid_keys(
        &self,
        req: FetchHybridKeysReq,
        _auth: &CallerAuth,
    ) -> Result<FetchHybridKeysResp, DomainError> {
        let mut keys = Vec::with_capacity(req.identity_keys.len());
        for ik in &req.identity_keys {
            let pk = self.store.fetch_hybrid_key(ik)?.unwrap_or_default();
            keys.push(pk);
        }
        Ok(FetchHybridKeysResp { keys })
    }
}
