//! Database Gateway - HTTP/REST API for Synor Database.
//!
//! Provides external access to database operations via REST API.
//!
//! # Endpoints
//!
//! ## Key-Value Operations
//! - `GET /kv/:key` - Get value
//! - `PUT /kv/:key` - Set value
//! - `DELETE /kv/:key` - Delete key
//! - `POST /kv/batch` - Batch operations
//!
//! ## Document Operations
//! - `POST /db/:database/collections` - Create collection
//! - `GET /db/:database/:collection` - Query documents
//! - `POST /db/:database/:collection` - Insert document
//! - `PUT /db/:database/:collection/:id` - Update document
//! - `DELETE /db/:database/:collection/:id` - Delete document
//!
//! ## Vector Operations
//! - `POST /db/:database/vectors` - Insert embeddings
//! - `POST /db/:database/vectors/search` - Similarity search
//!
//! ## Time-Series Operations
//! - `POST /db/:database/metrics/:name` - Record metric
//! - `GET /db/:database/metrics/:name` - Query metrics

pub mod auth;
pub mod handlers;
pub mod router;
pub mod server;

pub use auth::{ApiKey, AuthConfig, AuthMiddleware};
pub use router::create_router;
pub use server::{GatewayConfig, GatewayServer};

use crate::error::DatabaseError;
use serde::{Deserialize, Serialize};

/// API response wrapper.
#[derive(Debug, Serialize, Deserialize)]
pub struct ApiResponse<T> {
    /// Whether the request succeeded.
    pub success: bool,
    /// Response data (if successful).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub data: Option<T>,
    /// Error message (if failed).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub error: Option<String>,
    /// Request ID for tracing.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub request_id: Option<String>,
}

impl<T> ApiResponse<T> {
    /// Creates a successful response.
    pub fn ok(data: T) -> Self {
        Self {
            success: true,
            data: Some(data),
            error: None,
            request_id: None,
        }
    }

    /// Creates an error response.
    pub fn error(message: impl Into<String>) -> Self {
        Self {
            success: false,
            data: None,
            error: Some(message.into()),
            request_id: None,
        }
    }

    /// Sets the request ID.
    pub fn with_request_id(mut self, id: impl Into<String>) -> Self {
        self.request_id = Some(id.into());
        self
    }
}

impl<T> From<Result<T, DatabaseError>> for ApiResponse<T> {
    fn from(result: Result<T, DatabaseError>) -> Self {
        match result {
            Ok(data) => ApiResponse::ok(data),
            Err(e) => ApiResponse::error(e.to_string()),
        }
    }
}

/// Pagination parameters.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Pagination {
    /// Number of items to skip.
    #[serde(default)]
    pub skip: usize,
    /// Maximum items to return.
    #[serde(default = "default_limit")]
    pub limit: usize,
}

fn default_limit() -> usize {
    100
}

impl Default for Pagination {
    fn default() -> Self {
        Self {
            skip: 0,
            limit: default_limit(),
        }
    }
}

/// Usage metrics for billing.
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct UsageMetrics {
    /// Read operations count.
    pub reads: u64,
    /// Write operations count.
    pub writes: u64,
    /// Vector search operations.
    pub vector_searches: u64,
    /// Storage used (bytes).
    pub storage_bytes: u64,
    /// Data transferred (bytes).
    pub bandwidth_bytes: u64,
}
