//! Claim storage interface and implementations.
//!
//! Provides persistence for human-authored claims (not observations).
//! Claims are stored in `.aphoria/claims.toml` for version control.

use crate::types::AuthoredClaim;
use crate::AphoriaError;
use std::path::PathBuf;

/// Filter criteria for querying claims.
#[derive(Debug, Clone, Default)]
pub struct ClaimFilter {
    /// Filter by concept path (exact match)
    pub concept_path: Option<String>,

    /// Filter by predicate (exact match)
    pub predicate: Option<String>,

    /// Filter by authority tier
    pub authority_tier: Option<u8>,
}

/// Statistics from bulk import operations.
#[derive(Debug, Default)]
pub struct ImportStats {
    /// Number of claims successfully imported
    pub imported: usize,

    /// Number of claims skipped (duplicates)
    pub skipped: usize,

    /// Number of claims that failed to import
    pub errors: usize,
}

/// Trait for claim storage backends.
///
/// Implementations provide persistence for `AuthoredClaim` instances.
/// The primary implementation is `TomlClaimStore` which stores claims
/// in `.aphoria/claims.toml` for version control.
pub trait ClaimStore: Send + Sync {
    /// Save a new claim or update an existing one.
    ///
    /// Claims are identified by `(concept_path, predicate)` tuple.
    /// If a claim with the same tuple exists, it is replaced.
    fn save_claim(&self, claim: &AuthoredClaim) -> Result<(), AphoriaError>;

    /// Load a specific claim by concept path and predicate.
    fn load_claim(
        &self,
        concept_path: &str,
        predicate: &str,
    ) -> Result<Option<AuthoredClaim>, AphoriaError>;

    /// List all claims matching the filter criteria.
    ///
    /// If filter is empty (all fields None), returns all claims.
    fn list_claims(&self, filter: &ClaimFilter) -> Result<Vec<AuthoredClaim>, AphoriaError>;

    /// Delete a claim by concept path and predicate.
    ///
    /// Returns `true` if a claim was deleted, `false` if not found.
    fn delete_claim(&self, concept_path: &str, predicate: &str) -> Result<bool, AphoriaError>;

    /// Import multiple claims in bulk.
    ///
    /// Duplicates (same concept_path + predicate) are skipped.
    fn import_claims(&self, claims: &[AuthoredClaim]) -> Result<ImportStats, AphoriaError> {
        let mut stats = ImportStats::default();

        for claim in claims {
            match self.save_claim(claim) {
                Ok(()) => stats.imported += 1,
                Err(_) => stats.errors += 1,
            }
        }

        Ok(stats)
    }

    /// Export claims matching filter criteria.
    fn export_claims(&self, filter: &ClaimFilter) -> Result<Vec<AuthoredClaim>, AphoriaError> {
        self.list_claims(filter)
    }
}

/// File-based claim storage using TOML format.
///
/// Stores claims in `.aphoria/claims.toml` relative to the base directory.
/// This allows claims to be version-controlled alongside code.
///
/// # Note
///
/// This is a stub implementation. The `ClaimStore` trait is not yet implemented
/// for this struct.
// TODO(A4): Implement `ClaimStore for TomlClaimStore` using ClaimsFile for persistence.
#[allow(dead_code)]
pub struct TomlClaimStore {
    base_dir: PathBuf,
}

#[allow(dead_code)]
impl TomlClaimStore {
    /// Create a new TOML claim store.
    ///
    /// # Arguments
    ///
    /// * `base_dir` - Project root directory (claims stored in `{base_dir}/.aphoria/claims.toml`)
    pub fn new(base_dir: PathBuf) -> Self {
        Self { base_dir }
    }

    /// Get the path to the claims file.
    fn claims_file(&self) -> PathBuf {
        self.base_dir.join(".aphoria").join("claims.toml")
    }
}

// Implementation will be added in Commit 4 (Claim Storage)
// For now, this is just the trait interface.
