//! Database types

use serde::{Deserialize, Serialize};
use std::collections::HashMap;

/// Network environment
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "lowercase")]
pub enum Network {
    #[default]
    Mainnet,
    Testnet,
    Devnet,
}

/// Database configuration
#[derive(Debug, Clone)]
pub struct Config {
    pub api_key: String,
    pub endpoint: String,
    pub network: Network,
    pub timeout_secs: u64,
    pub retries: u32,
    pub debug: bool,
}

impl Default for Config {
    fn default() -> Self {
        Self {
            api_key: String::new(),
            endpoint: "https://database.synor.io/v1".to_string(),
            network: Network::Mainnet,
            timeout_secs: 30,
            retries: 3,
            debug: false,
        }
    }
}

// ==================== Key-Value Types ====================

/// Key-value entry with metadata
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct KeyValueEntry<T = serde_json::Value> {
    pub key: String,
    pub value: T,
    #[serde(default)]
    pub metadata: Option<HashMap<String, String>>,
    #[serde(default)]
    pub expires_at: Option<i64>,
    pub created_at: i64,
    pub updated_at: i64,
}

/// Options for setting a key-value pair
#[derive(Debug, Clone, Default, Serialize)]
pub struct SetOptions {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub ttl: Option<i64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub metadata: Option<HashMap<String, String>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub if_not_exists: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub if_exists: Option<bool>,
}

/// Options for listing keys
#[derive(Debug, Clone, Default, Serialize)]
pub struct ListOptions {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub prefix: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub cursor: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub limit: Option<u32>,
}

/// Result of listing keys
#[derive(Debug, Clone, Deserialize)]
pub struct ListResult<T = serde_json::Value> {
    pub entries: Vec<KeyValueEntry<T>>,
    pub cursor: Option<String>,
    pub has_more: bool,
}

// ==================== Document Store Types ====================

/// A document with metadata
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Document<T = serde_json::Value> {
    pub id: String,
    pub data: T,
    #[serde(default)]
    pub metadata: Option<HashMap<String, String>>,
    pub created_at: i64,
    pub updated_at: i64,
    pub version: i32,
}

/// Options for creating a document
#[derive(Debug, Clone, Default, Serialize)]
pub struct CreateDocumentOptions {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub id: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub metadata: Option<HashMap<String, String>>,
}

/// Options for updating a document
#[derive(Debug, Clone, Default, Serialize)]
pub struct UpdateDocumentOptions {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub upsert: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub return_document: Option<String>,
}

/// Sort order
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum SortOrder {
    Asc,
    Desc,
}

/// Query options for document store
#[derive(Debug, Clone, Default, Serialize)]
pub struct QueryOptions {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub filter: Option<serde_json::Value>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub sort: Option<HashMap<String, SortOrder>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub skip: Option<u32>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub limit: Option<u32>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub projection: Option<Vec<String>>,
}

/// Result of a document query
#[derive(Debug, Clone, Deserialize)]
pub struct QueryResult<T = serde_json::Value> {
    pub documents: Vec<Document<T>>,
    pub total: u64,
    pub has_more: bool,
}

// ==================== Vector Store Types ====================

/// A vector entry
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct VectorEntry {
    pub id: String,
    pub vector: Vec<f64>,
    #[serde(default)]
    pub metadata: Option<serde_json::Value>,
    #[serde(default)]
    pub content: Option<String>,
}

/// Vector distance metric
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub enum DistanceMetric {
    #[default]
    Cosine,
    Euclidean,
    DotProduct,
}

/// Options for upserting vectors
#[derive(Debug, Clone, Default, Serialize)]
pub struct UpsertVectorOptions {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub namespace: Option<String>,
}

/// Options for vector search
#[derive(Debug, Clone, Default, Serialize)]
pub struct SearchOptions {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub namespace: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub top_k: Option<u32>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub filter: Option<serde_json::Value>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub include_metadata: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub include_vectors: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub min_score: Option<f64>,
}

/// Result of a vector search
#[derive(Debug, Clone, Deserialize)]
pub struct SearchResult {
    pub id: String,
    pub score: f64,
    #[serde(default)]
    pub vector: Option<Vec<f64>>,
    #[serde(default)]
    pub metadata: Option<serde_json::Value>,
    #[serde(default)]
    pub content: Option<String>,
}

/// Configuration for a vector collection
#[derive(Debug, Clone, Serialize)]
pub struct VectorCollectionConfig {
    pub name: String,
    pub dimension: u32,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub metric: Option<DistanceMetric>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub index_type: Option<String>,
}

/// Statistics for a vector collection
#[derive(Debug, Clone, Deserialize)]
pub struct VectorCollectionStats {
    pub name: String,
    pub vector_count: u64,
    pub dimension: u32,
    pub index_size: u64,
}

// ==================== Time Series Types ====================

/// A time series data point
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DataPoint {
    pub timestamp: i64,
    pub value: f64,
    #[serde(default)]
    pub tags: Option<HashMap<String, String>>,
}

/// Options for writing data points
#[derive(Debug, Clone, Default, Serialize)]
pub struct WritePointsOptions {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub precision: Option<String>,
}

/// Time series aggregation function
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Aggregation {
    Mean,
    Sum,
    Count,
    Min,
    Max,
    First,
    Last,
    Stddev,
    Variance,
}

/// Time range for queries
#[derive(Debug, Clone, Serialize)]
pub struct TimeRange {
    pub start: serde_json::Value,
    pub end: serde_json::Value,
}

impl TimeRange {
    pub fn new(start: i64, end: i64) -> Self {
        Self {
            start: serde_json::Value::Number(start.into()),
            end: serde_json::Value::Number(end.into()),
        }
    }

    pub fn from_strings(start: &str, end: &str) -> Self {
        Self {
            start: serde_json::Value::String(start.to_string()),
            end: serde_json::Value::String(end.to_string()),
        }
    }
}

/// Options for time series queries
#[derive(Debug, Clone, Default, Serialize)]
pub struct TimeSeriesQueryOptions {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub tags: Option<HashMap<String, String>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub aggregation: Option<Aggregation>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub interval: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub fill: Option<serde_json::Value>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub limit: Option<u32>,
}

/// Result of a time series query
#[derive(Debug, Clone, Deserialize)]
pub struct TimeSeriesResult {
    pub series: String,
    pub points: Vec<DataPoint>,
    #[serde(default)]
    pub statistics: Option<HashMap<String, f64>>,
}

/// Information about a time series
#[derive(Debug, Clone, Deserialize)]
pub struct SeriesInfo {
    pub name: String,
    pub tags: Vec<String>,
    pub retention_days: i32,
    pub point_count: u64,
}

// ==================== Database Stats ====================

/// Overall database statistics
#[derive(Debug, Clone, Deserialize)]
pub struct DatabaseStats {
    pub kv_entries: u64,
    pub document_count: u64,
    pub vector_count: u64,
    pub timeseries_points: u64,
    pub storage_used: u64,
    pub storage_limit: u64,
}
