/**
 * Synor Database SDK Types
 * Multi-model database: Key-Value, Document, Vector, and Time Series
 */

// Network environments
export type DatabaseNetwork = 'mainnet' | 'testnet' | 'devnet';

// Database configuration
export interface DatabaseConfig {
  apiKey: string;
  endpoint?: string;
  network?: DatabaseNetwork;
  timeout?: number;
  retries?: number;
  debug?: boolean;
}

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

export interface KeyValueEntry<T = unknown> {
  key: string;
  value: T;
  metadata?: Record<string, string>;
  expiresAt?: number;
  createdAt: number;
  updatedAt: number;
}

export interface SetOptions {
  ttl?: number; // Time-to-live in seconds
  metadata?: Record<string, string>;
  ifNotExists?: boolean;
  ifExists?: boolean;
}

export interface ListOptions {
  prefix?: string;
  cursor?: string;
  limit?: number;
}

export interface ListResult<T = unknown> {
  entries: KeyValueEntry<T>[];
  cursor?: string;
  hasMore: boolean;
}

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

export interface Document<T = Record<string, unknown>> {
  id: string;
  data: T;
  metadata?: Record<string, string>;
  createdAt: number;
  updatedAt: number;
  version: number;
}

export interface CreateDocumentOptions {
  id?: string; // Auto-generate if not provided
  metadata?: Record<string, string>;
}

export interface UpdateDocumentOptions {
  upsert?: boolean;
  returnDocument?: 'before' | 'after';
}

export type QueryOperator =
  | '$eq' | '$ne' | '$gt' | '$gte' | '$lt' | '$lte'
  | '$in' | '$nin' | '$exists' | '$regex'
  | '$and' | '$or' | '$not';

export type QueryFilter = {
  [field: string]: unknown | { [K in QueryOperator]?: unknown };
};

export type SortOrder = 'asc' | 'desc';

export interface QueryOptions {
  filter?: QueryFilter;
  sort?: { [field: string]: SortOrder };
  skip?: number;
  limit?: number;
  projection?: string[];
}

export interface QueryResult<T = Record<string, unknown>> {
  documents: Document<T>[];
  total: number;
  hasMore: boolean;
}

export interface AggregateStage {
  $match?: QueryFilter;
  $group?: { _id: string; [field: string]: { $sum?: string; $avg?: string; $count?: boolean; $min?: string; $max?: string } };
  $sort?: { [field: string]: SortOrder };
  $limit?: number;
  $skip?: number;
  $project?: { [field: string]: boolean | string };
}

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

export interface VectorEntry {
  id: string;
  vector: number[];
  metadata?: Record<string, unknown>;
  content?: string; // Optional text content for hybrid search
}

export interface UpsertVectorOptions {
  namespace?: string;
}

export type DistanceMetric = 'cosine' | 'euclidean' | 'dotProduct';

export interface SearchOptions {
  namespace?: string;
  topK?: number;
  filter?: QueryFilter;
  includeMetadata?: boolean;
  includeVectors?: boolean;
  minScore?: number;
}

export interface SearchResult {
  id: string;
  score: number;
  vector?: number[];
  metadata?: Record<string, unknown>;
  content?: string;
}

export interface VectorCollectionConfig {
  name: string;
  dimension: number;
  metric?: DistanceMetric;
  indexType?: 'flat' | 'hnsw' | 'ivf';
}

export interface VectorCollectionStats {
  name: string;
  vectorCount: number;
  dimension: number;
  indexSize: number;
}

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

export interface DataPoint {
  timestamp: number;
  value: number;
  tags?: Record<string, string>;
}

export interface WritePointsOptions {
  precision?: 'ns' | 'us' | 'ms' | 's';
}

export type Aggregation =
  | 'mean' | 'sum' | 'count' | 'min' | 'max'
  | 'first' | 'last' | 'stddev' | 'variance';

export interface TimeRange {
  start: number | Date | string;
  end: number | Date | string;
}

export interface TimeSeriesQueryOptions {
  tags?: Record<string, string>;
  aggregation?: Aggregation;
  interval?: string; // e.g., '1m', '5m', '1h', '1d'
  fill?: 'none' | 'null' | 'previous' | number;
  limit?: number;
}

export interface TimeSeriesResult {
  series: string;
  points: DataPoint[];
  statistics?: {
    min: number;
    max: number;
    mean: number;
    count: number;
  };
}

export interface SeriesInfo {
  name: string;
  tags: string[];
  retentionDays: number;
  pointCount: number;
}

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

export interface DatabaseStats {
  kvEntries: number;
  documentCount: number;
  vectorCount: number;
  timeseriesPoints: number;
  storageUsed: number;
  storageLimit: number;
}

// ==================== Error Types ====================

export class DatabaseError extends Error {
  code?: string;
  statusCode?: number;

  constructor(message: string, code?: string, statusCode?: number) {
    super(message);
    this.name = 'DatabaseError';
    this.code = code;
    this.statusCode = statusCode;
  }
}

export class DocumentNotFoundError extends DatabaseError {
  constructor(collection: string, id: string) {
    super(`Document not found: ${collection}/${id}`, 'DOCUMENT_NOT_FOUND', 404);
    this.name = 'DocumentNotFoundError';
  }
}

export class KeyNotFoundError extends DatabaseError {
  constructor(key: string) {
    super(`Key not found: ${key}`, 'KEY_NOT_FOUND', 404);
    this.name = 'KeyNotFoundError';
  }
}
