//! Bridge between the gRPC `SyncStorage` trait and stemedb-api's storage layer.
//!
//! This module allows the stemedb-api binary to host a gRPC sync server that
//! delegates to the same `HybridStore` and `MerkleTreeManager` used by the
//! main HTTP API.

use async_trait::async_trait;
use std::sync::Arc;
use stemedb_merkle::Hash;
use stemedb_rpc::server::SyncStorage;
use stemedb_storage::{HybridStore, KVStore};
use stemedb_sync::MerkleTreeManager;
use tracing::{debug, warn};

/// Bridges the gRPC `SyncStorage` trait to the stemedb-api storage layer.
pub struct SyncStorageBridge {
    kv_store: Arc<HybridStore>,
    merkle_manager: Arc<MerkleTreeManager<HybridStore>>,
    local_node_id: [u8; 16],
    rpc_addr: String,
    api_addr: String,
}

impl SyncStorageBridge {
    /// Creates a new bridge.
    pub fn new(
        kv_store: Arc<HybridStore>,
        merkle_manager: Arc<MerkleTreeManager<HybridStore>>,
        local_node_id: [u8; 16],
        rpc_addr: String,
        api_addr: String,
    ) -> Self {
        Self { kv_store, merkle_manager, local_node_id, rpc_addr, api_addr }
    }
}

#[async_trait]
impl SyncStorage for SyncStorageBridge {
    async fn store_gossip_assertion(
        &self,
        hash: [u8; 32],
        data: Vec<u8>,
        _hlc_time: u64,
        _hlc_counter: u32,
        _hlc_node_id: [u8; 16],
    ) -> Result<bool, String> {
        // Content-addressed key: store at "A:{hash}"
        let key = format!("A:{}", ::hex::encode(hash));

        // Check if already exists
        match self.kv_store.get(key.as_bytes()).await {
            Ok(Some(_)) => {
                debug!(hash = %::hex::encode(&hash[..8]), "Gossip assertion already exists");
                return Ok(false);
            }
            Ok(None) => {}
            Err(e) => return Err(format!("KV get failed: {e}")),
        }

        // Store the assertion data
        self.kv_store
            .put(key.as_bytes(), &data)
            .await
            .map_err(|e| format!("KV put failed: {e}"))?;

        // Insert hash into Merkle tree
        self.merkle_manager.insert(hash).await.map_err(|e| format!("Merkle insert failed: {e}"))?;

        Ok(true)
    }

    async fn get_merkle_state(&self) -> Result<(Option<[u8; 32]>, u64), String> {
        let root =
            self.merkle_manager.root().await.map_err(|e| format!("Merkle root failed: {e}"))?;
        let count = self.merkle_manager.len().await as u64;
        Ok((root, count))
    }

    async fn fetch_assertions(
        &self,
        hashes: Vec<[u8; 32]>,
    ) -> Result<Vec<([u8; 32], Vec<u8>)>, String> {
        let mut results = Vec::with_capacity(hashes.len());
        for hash in hashes {
            let key = format!("A:{}", ::hex::encode(hash));
            match self.kv_store.get(key.as_bytes()).await {
                Ok(Some(data)) => results.push((hash, data)),
                Ok(None) => {
                    debug!(hash = %::hex::encode(&hash[..8]), "Assertion not found");
                }
                Err(e) => {
                    warn!(error = %e, "Failed to fetch assertion");
                }
            }
        }
        Ok(results)
    }

    async fn get_node_info(&self) -> Result<([u8; 16], u64, String, String), String> {
        let count = self.merkle_manager.len().await as u64;
        Ok((self.local_node_id, count, self.rpc_addr.clone(), self.api_addr.clone()))
    }

    async fn get_leaves(&self, max_leaves: u64) -> Result<(Vec<Hash>, bool), String> {
        let all_leaves = self.merkle_manager.leaves().await;
        let cap = if max_leaves == 0 { 10000 } else { max_leaves.min(10000) as usize };
        if all_leaves.len() > cap {
            Ok((all_leaves.into_iter().take(cap).collect(), true))
        } else {
            Ok((all_leaves, false))
        }
    }
}
