//! TrustGraphStore implementation backed by a generic KVStore.
//!
//! This module provides the concrete implementation of TrustGraphStore operations,
//! including edge management, seed trust, and EigenTrust computation.

use crate::error::Result;
use crate::key_codec;
use crate::traits::KVStore;
use async_trait::async_trait;
use tracing::{debug, instrument};

use super::eigentrust::compute_eigentrust_scores;
use super::model::{EigenTrustConfig, EigenTrustState, TrustEdge};
use super::TrustGraphStore;

/// TrustGraphStore implementation backed by a generic KVStore.
///
/// This implementation stores trust edges and EigenTrust state using the
/// key patterns defined in `key_codec`.
pub struct GenericTrustGraphStore<S> {
    store: S,
}

impl<S: KVStore> GenericTrustGraphStore<S> {
    /// Create a new TrustGraphStore backed by the given KVStore.
    pub fn new(store: S) -> Self {
        Self { store }
    }

    /// Serialize a TrustEdge using the canonical serde helpers.
    fn serialize_edge(edge: &TrustEdge) -> Result<Vec<u8>> {
        crate::serde_helpers::serialize(edge)
    }

    /// Deserialize a TrustEdge using the canonical serde helpers.
    fn deserialize_edge(data: &[u8]) -> Result<TrustEdge> {
        crate::serde_helpers::deserialize(data)
    }

    /// Serialize an EigenTrustState using the canonical serde helpers.
    fn serialize_state(state: &EigenTrustState) -> Result<Vec<u8>> {
        crate::serde_helpers::serialize(state)
    }

    /// Deserialize an EigenTrustState using the canonical serde helpers.
    fn deserialize_state(data: &[u8]) -> Result<EigenTrustState> {
        crate::serde_helpers::deserialize(data)
    }

    /// Extract agent ID from a seed trust key.
    ///
    /// Key format: `\x00ET:seed:{agent_hex}`
    fn extract_agent_from_seed_key(key: &[u8]) -> Option<[u8; 32]> {
        let prefix = b"\x00ET:seed:";
        if !key.starts_with(prefix) {
            return None;
        }

        let hex_str = std::str::from_utf8(&key[prefix.len()..]).ok()?;
        let bytes = hex::decode(hex_str).ok()?;
        if bytes.len() != 32 {
            return None;
        }

        let mut arr = [0u8; 32];
        arr.copy_from_slice(&bytes);
        Some(arr)
    }

    /// Extract (from, to) agent IDs from a trust edge key.
    ///
    /// Key format: `\x00TG:{from_hex}:{to_hex}`
    fn extract_agents_from_edge_key(key: &[u8]) -> Option<([u8; 32], [u8; 32])> {
        let prefix = b"\x00TG:";
        if !key.starts_with(prefix) {
            return None;
        }

        let rest = std::str::from_utf8(&key[prefix.len()..]).ok()?;
        let parts: Vec<&str> = rest.split(':').collect();
        if parts.len() != 2 {
            return None;
        }

        let from_bytes = hex::decode(parts[0]).ok()?;
        let to_bytes = hex::decode(parts[1]).ok()?;

        if from_bytes.len() != 32 || to_bytes.len() != 32 {
            return None;
        }

        let mut from = [0u8; 32];
        let mut to = [0u8; 32];
        from.copy_from_slice(&from_bytes);
        to.copy_from_slice(&to_bytes);

        Some((from, to))
    }
}

#[async_trait]
impl<S: KVStore + 'static> TrustGraphStore for GenericTrustGraphStore<S> {
    #[instrument(skip(self, edge), fields(
        from = %hex::encode(edge.from_agent),
        to = %hex::encode(edge.to_agent),
        weight = edge.weight
    ))]
    async fn add_trust_edge(&self, edge: &TrustEdge) -> Result<()> {
        let from_hex = hex::encode(edge.from_agent);
        let to_hex = hex::encode(edge.to_agent);

        // Store forward index
        let forward_key = key_codec::trust_edge_key(&from_hex, &to_hex);
        let serialized = Self::serialize_edge(edge)?;
        self.store.put(&forward_key, &serialized).await?;

        // Store reverse index (same data, different key)
        let reverse_key = key_codec::trust_edge_reverse_key(&to_hex, &from_hex);
        self.store.put(&reverse_key, &serialized).await?;

        debug!("Added trust edge");
        Ok(())
    }

    #[instrument(skip(self), fields(from = %hex::encode(from), to = %hex::encode(to)))]
    async fn remove_trust_edge(&self, from: &[u8; 32], to: &[u8; 32]) -> Result<bool> {
        let from_hex = hex::encode(from);
        let to_hex = hex::encode(to);

        let forward_key = key_codec::trust_edge_key(&from_hex, &to_hex);
        let exists = self.store.get(&forward_key).await?.is_some();

        if exists {
            // Delete forward index
            self.store.delete(&forward_key).await?;

            // Delete reverse index
            let reverse_key = key_codec::trust_edge_reverse_key(&to_hex, &from_hex);
            self.store.delete(&reverse_key).await?;

            debug!("Removed trust edge");
        }

        Ok(exists)
    }

    #[instrument(skip(self), fields(from = %hex::encode(from), to = %hex::encode(to)))]
    async fn get_trust_edge(&self, from: &[u8; 32], to: &[u8; 32]) -> Result<Option<TrustEdge>> {
        let from_hex = hex::encode(from);
        let to_hex = hex::encode(to);

        let key = key_codec::trust_edge_key(&from_hex, &to_hex);
        match self.store.get(&key).await? {
            Some(data) => {
                let edge = Self::deserialize_edge(&data)?;
                Ok(Some(edge))
            }
            None => Ok(None),
        }
    }

    #[instrument(skip(self), fields(from = %hex::encode(from)))]
    async fn get_trusts(&self, from: &[u8; 32]) -> Result<Vec<([u8; 32], f32)>> {
        let from_hex = hex::encode(from);
        let prefix = key_codec::trust_edge_from_prefix(&from_hex);
        let entries = self.store.scan_prefix(&prefix).await?;

        let mut trusts = Vec::with_capacity(entries.len());
        for (_, data) in entries {
            let edge = Self::deserialize_edge(&data)?;
            trusts.push((edge.to_agent, edge.weight));
        }

        debug!(count = trusts.len(), "Retrieved outgoing trust edges");
        Ok(trusts)
    }

    #[instrument(skip(self), fields(to = %hex::encode(to)))]
    async fn get_trusted_by(&self, to: &[u8; 32]) -> Result<Vec<([u8; 32], f32)>> {
        let to_hex = hex::encode(to);
        let prefix = key_codec::trust_edge_reverse_prefix(&to_hex);
        let entries = self.store.scan_prefix(&prefix).await?;

        let mut trusted_by = Vec::with_capacity(entries.len());
        for (_, data) in entries {
            let edge = Self::deserialize_edge(&data)?;
            trusted_by.push((edge.from_agent, edge.weight));
        }

        debug!(count = trusted_by.len(), "Retrieved incoming trust edges");
        Ok(trusted_by)
    }

    #[instrument(skip(self))]
    async fn get_all_edges(&self) -> Result<Vec<TrustEdge>> {
        let prefix = key_codec::trust_graph_scan_prefix();
        let entries = self.store.scan_prefix(&prefix).await?;

        let mut edges = Vec::with_capacity(entries.len());
        for (key, data) in entries {
            // Only process forward index keys (skip reverse index)
            if Self::extract_agents_from_edge_key(&key).is_some() {
                let edge = Self::deserialize_edge(&data)?;
                edges.push(edge);
            }
        }

        debug!(count = edges.len(), "Retrieved all trust edges");
        Ok(edges)
    }

    #[instrument(skip(self), fields(agent = %hex::encode(agent), trust))]
    async fn set_seed_trust(&self, agent: &[u8; 32], trust: f32) -> Result<()> {
        let agent_hex = hex::encode(agent);
        let key = key_codec::seed_trust_key(&agent_hex);

        // Store as f32 bytes
        let clamped = trust.clamp(0.0, 1.0);
        let bytes = clamped.to_le_bytes();
        self.store.put(&key, &bytes).await?;

        debug!("Set seed trust");
        Ok(())
    }

    #[instrument(skip(self), fields(agent = %hex::encode(agent)))]
    async fn get_seed_trust(&self, agent: &[u8; 32]) -> Result<f32> {
        let agent_hex = hex::encode(agent);
        let key = key_codec::seed_trust_key(&agent_hex);

        match self.store.get(&key).await? {
            Some(data) if data.len() == 4 => {
                let bytes: [u8; 4] = data[..4].try_into().map_err(|_| {
                    crate::error::StorageError::Serialization("Invalid f32 bytes".to_string())
                })?;
                Ok(f32::from_le_bytes(bytes))
            }
            _ => Ok(0.0),
        }
    }

    #[instrument(skip(self))]
    async fn get_all_seed_trust(&self) -> Result<Vec<([u8; 32], f32)>> {
        let prefix = key_codec::seed_trust_scan_prefix();
        let entries = self.store.scan_prefix(&prefix).await?;

        let mut seeds = Vec::with_capacity(entries.len());
        for (key, data) in entries {
            if let Some(agent) = Self::extract_agent_from_seed_key(&key) {
                if data.len() == 4 {
                    let bytes: [u8; 4] = data[..4].try_into().map_err(|_| {
                        crate::error::StorageError::Serialization("Invalid f32 bytes".to_string())
                    })?;
                    let trust = f32::from_le_bytes(bytes);
                    seeds.push((agent, trust));
                }
            }
        }

        debug!(count = seeds.len(), "Retrieved all seed trust entries");
        Ok(seeds)
    }

    #[instrument(skip(self), fields(agent = %hex::encode(agent)))]
    async fn remove_seed_trust(&self, agent: &[u8; 32]) -> Result<bool> {
        let agent_hex = hex::encode(agent);
        let key = key_codec::seed_trust_key(&agent_hex);

        let exists = self.store.get(&key).await?.is_some();
        if exists {
            self.store.delete(&key).await?;
            debug!("Removed seed trust");
        }

        Ok(exists)
    }

    #[instrument(skip(self, config))]
    async fn compute_eigentrust(&self, config: &EigenTrustConfig) -> Result<EigenTrustState> {
        // Get all edges and seed trust
        let edges = self.get_all_edges().await?;
        let seeds = self.get_all_seed_trust().await?;

        // Get current timestamp
        let timestamp = std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .map(|d| d.as_secs())
            .unwrap_or_else(|e| {
                tracing::warn!(error = %e, "System clock error, using epoch timestamp");
                0
            });

        // Run EigenTrust algorithm
        let result = compute_eigentrust_scores(&edges, &seeds, config, timestamp);

        // Store the computed state
        let state_key = key_codec::eigentrust_state_key();
        let serialized = Self::serialize_state(&result.state)?;
        self.store.put(&state_key, &serialized).await?;

        debug!(
            converged = result.converged,
            iterations = result.state.iterations,
            agents = result.state.scores.len(),
            "Computed and stored EigenTrust state"
        );

        Ok(result.state)
    }

    #[instrument(skip(self))]
    async fn get_eigentrust_state(&self) -> Result<Option<EigenTrustState>> {
        let key = key_codec::eigentrust_state_key();
        match self.store.get(&key).await? {
            Some(data) => {
                let state = Self::deserialize_state(&data)?;
                Ok(Some(state))
            }
            None => Ok(None),
        }
    }

    #[instrument(skip(self), fields(agent = %hex::encode(agent)))]
    async fn get_eigentrust_score(&self, agent: &[u8; 32]) -> Result<f32> {
        match self.get_eigentrust_state().await? {
            Some(state) => Ok(state.get_score(agent)),
            None => Ok(0.0),
        }
    }
}
