//! Trading Data Repository
//!
//! This crate provides repository pattern implementations for trading data persistence
//! in high-frequency trading systems. It includes repositories for orders, positions,
//! and executions with `PostgreSQL` backing.
//!
//! # Features
//!
//! - Clean repository pattern with trait-based interfaces
//! - Type-safe database operations with `SQLx`
//! - Comprehensive error handling
//! - Async/await support for high-performance operations
//! - Production-ready patterns for HFT systems
//!
//! # Architecture
//!
//! The crate follows the repository pattern with trait definitions and `PostgreSQL`
//! implementations. Each domain entity (Order, Position, Execution) has its own
//! repository with both basic CRUD operations and domain-specific queries.
//!
//! # Usage
//!
//! ```rust,no_run
//! use trading_data::{PostgresOrderRepository, OrderRepository};
//! use sqlx::postgres::PgPool;
//!
//! # async fn example(pool: PgPool) -> Result<(), Box<dyn std::error::Error>> {
//! let order_repo = PostgresOrderRepository::new(pool);
//! let orders = order_repo.find_active_orders().await?;
//! # Ok(())
//! # }
//! ```

#![deny(missing_docs)]
#![deny(clippy::unwrap_used, clippy::expect_used)]
#![warn(clippy::all)]
#![warn(clippy::pedantic)]
#![allow(clippy::module_name_repetitions)]

pub mod executions;
pub mod models;
pub mod orders;
pub mod positions;

// Re-export repository types for public API
pub use executions::{ExecutionRepository, PostgresExecutionRepository};
pub use orders::{OrderRepository, PostgresOrderRepository};
pub use positions::{PositionRepository, PostgresPositionRepository};

/// Result type alias for repository operations
pub type Result<T> = std::result::Result<T, RepositoryError>;

/// Common error types for repository operations
#[derive(Debug, thiserror::Error)]
pub enum RepositoryError {
    /// Database operation failed (wraps `SQLx` errors)
    #[error("Database error: {0}")]
    Database(#[from] sqlx::Error),

    /// Input validation failed
    #[error("Validation error: {0}")]
    Validation(String),

    /// Requested entity was not found
    #[error("Entity not found: {0}")]
    NotFound(String),

    /// Operation conflicts with existing state
    #[error("Conflict: {0}")]
    Conflict(String),

    /// Internal repository error (wraps anyhow errors)
    #[error("Internal error: {0}")]
    Internal(#[from] anyhow::Error),
}

/// Common repository trait for basic CRUD operations
#[async_trait::async_trait]
pub trait Repository<T, ID> {
    /// Find entity by ID
    async fn find_by_id(&self, id: &ID) -> Result<Option<T>>;

    /// Save entity (insert or update)
    async fn save(&self, entity: &T) -> Result<T>;

    /// Delete entity by ID
    async fn delete(&self, id: &ID) -> Result<bool>;

    /// Check if entity exists by ID
    async fn exists(&self, id: &ID) -> Result<bool>;
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_error_types() {
        let validation_error = RepositoryError::Validation("test validation".to_string());
        assert!(matches!(validation_error, RepositoryError::Validation(_)));

        let not_found_error = RepositoryError::NotFound("test entity".to_string());
        assert!(matches!(not_found_error, RepositoryError::NotFound(_)));
    }
}
