//! Core Traits for Heterogeneous Storage Federation
//!
//! This module defines the unified `Store` trait that all storage types must implement.

use std::any::Any;
use std::sync::Arc;

use super::error::Result;
use super::types::{
    StoreType, Record, WriteOp, WriteResult, BatchWriteResult, UniversalQuery,
    OwnershipMeta,
};

/// Trait for downcasting to concrete types
pub trait AsAny: 'static + Send + Sync {
    fn as_any(&self) -> &dyn Any;
    fn as_any_arc(self: Arc<Self>) -> Arc<dyn Any + Send + Sync>;
}

/// Local transaction handle for a single store
pub trait LocalTransaction: Send + Sync {
    /// Get the store alias this transaction belongs to
    fn store_alias(&self) -> &str;
    
    /// Write an operation to the transaction
    fn write(&mut self, op: WriteOp) -> Result<()>;
    
    /// Prepare the transaction (2PC phase 1)
    fn prepare(&mut self) -> Result<bool>;
    
    /// Commit the transaction (2PC phase 2)
    fn commit(&mut self) -> Result<()>;
    
    /// Rollback the transaction
    fn rollback(&mut self) -> Result<()>;
}

/// Unified Store Trait - All storage types must implement this
///
/// This trait provides a common interface for different storage backends:
/// - Graph stores (SocialStoreV2)
/// - Document stores (EnhancedDocumentStore)
/// - Vector stores (ConcurrentVectorStore)
pub trait Store: Send + Sync + AsAny {
    /// Return the store type
    fn store_type(&self) -> StoreType;
    
    /// Get the store alias
    fn alias(&self) -> &str;
    
    /// Execute a query and return results
    fn query(&self, q: &UniversalQuery) -> Result<Vec<Record>>;
    
    /// Execute a single write operation
    fn write(&self, op: WriteOp) -> Result<WriteResult>;
    
    /// Execute multiple write operations
    fn batch_write(&self, ops: Vec<WriteOp>) -> Result<BatchWriteResult>;
    
    /// Begin a local transaction
    fn begin_local_tx(&self) -> Result<Box<dyn LocalTransaction + Send>>;
    
    /// Get a single record by ID
    fn get(&self, id: &str) -> Result<Option<Record>>;
    
    /// Check if a record exists
    fn exists(&self, id: &str) -> Result<bool>;
    
    /// Stream query results (for large datasets)
    /// Returns an iterator that yields records one by one
    fn query_iter(&self, q: &UniversalQuery) -> Result<Box<dyn Iterator<Item = Result<Record>> + Send>>;
    
    /// Get store statistics
    fn stats(&self) -> StoreStats;
    
    /// Update the ownership metadata for a record
    ///
    /// Updates visibility, protection level, and collaborators on an existing record.
    /// The record must exist and must have ownership metadata (owner_id set).
    ///
    /// This is used by:
    /// - `downgrade_protection()` — change protection level
    /// - Collaborator management — add/update/remove collaborators
    /// - Visibility changes — update visibility settings
    fn update_ownership(&self, id: &str, ownership: OwnershipMeta) -> Result<()>;
    
    /// Sync/flush data to disk
    fn sync(&self) -> Result<()>;
    
    /// Close the store
    fn close(&self) -> Result<()>;
}

/// Store statistics
#[derive(Debug, Clone, Default)]
pub struct StoreStats {
    /// Total number of records
    pub record_count: usize,
    /// Total number of relations (for graph stores)
    pub relation_count: Option<usize>,
    /// Index size in bytes
    pub index_size_bytes: u64,
    /// Data size in bytes
    pub data_size_bytes: u64,
    /// Last modified timestamp
    pub last_modified: Option<u64>,
}

// Note: Blanket implementation for Arc<T> removed because Arc<T> cannot implement AsAny.
// Use Arc<dyn Store> directly or wrap stores in adapters.
