// Package database provides the Synor Database SDK for Go.
// Multi-model database: Key-Value, Document, Vector, and Time Series.
package database

import (
	"time"
)

// Network represents the network environment
type Network string

const (
	NetworkMainnet Network = "mainnet"
	NetworkTestnet Network = "testnet"
	NetworkDevnet  Network = "devnet"
)

// Config represents the database client configuration
type Config struct {
	APIKey   string
	Endpoint string
	Network  Network
	Timeout  time.Duration
	Retries  int
	Debug    bool
}

// DefaultConfig returns the default configuration
func DefaultConfig(apiKey string) Config {
	return Config{
		APIKey:   apiKey,
		Endpoint: "https://database.synor.io/v1",
		Network:  NetworkMainnet,
		Timeout:  30 * time.Second,
		Retries:  3,
		Debug:    false,
	}
}

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

// KeyValueEntry represents a key-value entry with metadata
type KeyValueEntry struct {
	Key       string            `json:"key"`
	Value     interface{}       `json:"value"`
	Metadata  map[string]string `json:"metadata,omitempty"`
	ExpiresAt *int64            `json:"expires_at,omitempty"`
	CreatedAt int64             `json:"created_at"`
	UpdatedAt int64             `json:"updated_at"`
}

// SetOptions represents options for setting a key-value pair
type SetOptions struct {
	TTL         *int              `json:"ttl,omitempty"`
	Metadata    map[string]string `json:"metadata,omitempty"`
	IfNotExists bool              `json:"if_not_exists,omitempty"`
	IfExists    bool              `json:"if_exists,omitempty"`
}

// ListOptions represents options for listing keys
type ListOptions struct {
	Prefix string `json:"prefix,omitempty"`
	Cursor string `json:"cursor,omitempty"`
	Limit  int    `json:"limit,omitempty"`
}

// ListResult represents the result of listing keys
type ListResult struct {
	Entries []KeyValueEntry `json:"entries"`
	Cursor  string          `json:"cursor,omitempty"`
	HasMore bool            `json:"has_more"`
}

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

// Document represents a document with metadata
type Document struct {
	ID        string                 `json:"id"`
	Data      map[string]interface{} `json:"data"`
	Metadata  map[string]string      `json:"metadata,omitempty"`
	CreatedAt int64                  `json:"created_at"`
	UpdatedAt int64                  `json:"updated_at"`
	Version   int                    `json:"version"`
}

// CreateDocumentOptions represents options for creating a document
type CreateDocumentOptions struct {
	ID       string            `json:"id,omitempty"`
	Metadata map[string]string `json:"metadata,omitempty"`
}

// UpdateDocumentOptions represents options for updating a document
type UpdateDocumentOptions struct {
	Upsert         bool   `json:"upsert,omitempty"`
	ReturnDocument string `json:"return_document,omitempty"` // "before" or "after"
}

// QueryFilter represents a query filter
type QueryFilter map[string]interface{}

// SortOrder represents a sort order
type SortOrder string

const (
	SortAsc  SortOrder = "asc"
	SortDesc SortOrder = "desc"
)

// QueryOptions represents options for querying documents
type QueryOptions struct {
	Filter     QueryFilter          `json:"filter,omitempty"`
	Sort       map[string]SortOrder `json:"sort,omitempty"`
	Skip       int                  `json:"skip,omitempty"`
	Limit      int                  `json:"limit,omitempty"`
	Projection []string             `json:"projection,omitempty"`
}

// QueryResult represents the result of a document query
type QueryResult struct {
	Documents []Document `json:"documents"`
	Total     int        `json:"total"`
	HasMore   bool       `json:"has_more"`
}

// AggregateStage represents a stage in an aggregation pipeline
type AggregateStage map[string]interface{}

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

// VectorEntry represents a vector entry
type VectorEntry struct {
	ID       string                 `json:"id"`
	Vector   []float64              `json:"vector"`
	Metadata map[string]interface{} `json:"metadata,omitempty"`
	Content  string                 `json:"content,omitempty"`
}

// DistanceMetric represents a vector distance metric
type DistanceMetric string

const (
	DistanceCosine     DistanceMetric = "cosine"
	DistanceEuclidean  DistanceMetric = "euclidean"
	DistanceDotProduct DistanceMetric = "dotProduct"
)

// UpsertVectorOptions represents options for upserting vectors
type UpsertVectorOptions struct {
	Namespace string `json:"namespace,omitempty"`
}

// SearchOptions represents options for vector search
type SearchOptions struct {
	Namespace       string      `json:"namespace,omitempty"`
	TopK            int         `json:"top_k,omitempty"`
	Filter          QueryFilter `json:"filter,omitempty"`
	IncludeMetadata bool        `json:"include_metadata,omitempty"`
	IncludeVectors  bool        `json:"include_vectors,omitempty"`
	MinScore        *float64    `json:"min_score,omitempty"`
}

// SearchResult represents a vector search result
type SearchResult struct {
	ID       string                 `json:"id"`
	Score    float64                `json:"score"`
	Vector   []float64              `json:"vector,omitempty"`
	Metadata map[string]interface{} `json:"metadata,omitempty"`
	Content  string                 `json:"content,omitempty"`
}

// VectorCollectionConfig represents configuration for a vector collection
type VectorCollectionConfig struct {
	Name      string         `json:"name"`
	Dimension int            `json:"dimension"`
	Metric    DistanceMetric `json:"metric,omitempty"`
	IndexType string         `json:"index_type,omitempty"`
}

// VectorCollectionStats represents statistics for a vector collection
type VectorCollectionStats struct {
	Name        string `json:"name"`
	VectorCount int    `json:"vector_count"`
	Dimension   int    `json:"dimension"`
	IndexSize   int64  `json:"index_size"`
}

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

// DataPoint represents a time series data point
type DataPoint struct {
	Timestamp int64             `json:"timestamp"`
	Value     float64           `json:"value"`
	Tags      map[string]string `json:"tags,omitempty"`
}

// WritePointsOptions represents options for writing data points
type WritePointsOptions struct {
	Precision string `json:"precision,omitempty"` // "ns", "us", "ms", "s"
}

// Aggregation represents a time series aggregation function
type Aggregation string

const (
	AggMean     Aggregation = "mean"
	AggSum      Aggregation = "sum"
	AggCount    Aggregation = "count"
	AggMin      Aggregation = "min"
	AggMax      Aggregation = "max"
	AggFirst    Aggregation = "first"
	AggLast     Aggregation = "last"
	AggStddev   Aggregation = "stddev"
	AggVariance Aggregation = "variance"
)

// TimeRange represents a time range for queries
type TimeRange struct {
	Start interface{} `json:"start"` // int64, time.Time, or string
	End   interface{} `json:"end"`   // int64, time.Time, or string
}

// TimeSeriesQueryOptions represents options for time series queries
type TimeSeriesQueryOptions struct {
	Tags        map[string]string `json:"tags,omitempty"`
	Aggregation Aggregation       `json:"aggregation,omitempty"`
	Interval    string            `json:"interval,omitempty"` // e.g., "1m", "5m", "1h"
	Fill        interface{}       `json:"fill,omitempty"`     // "none", "null", "previous", or number
	Limit       int               `json:"limit,omitempty"`
}

// TimeSeriesResult represents the result of a time series query
type TimeSeriesResult struct {
	Series     string            `json:"series"`
	Points     []DataPoint       `json:"points"`
	Statistics map[string]float64 `json:"statistics,omitempty"`
}

// SeriesInfo represents information about a time series
type SeriesInfo struct {
	Name          string   `json:"name"`
	Tags          []string `json:"tags"`
	RetentionDays int      `json:"retention_days"`
	PointCount    int64    `json:"point_count"`
}

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

// DatabaseStats represents overall database statistics
type DatabaseStats struct {
	KVEntries        int   `json:"kv_entries"`
	DocumentCount    int   `json:"document_count"`
	VectorCount      int   `json:"vector_count"`
	TimeseriesPoints int64 `json:"timeseries_points"`
	StorageUsed      int64 `json:"storage_used"`
	StorageLimit     int64 `json:"storage_limit"`
}

// ==================== Errors ====================

// DatabaseError represents a database error
type DatabaseError struct {
	Message    string
	Code       string
	StatusCode int
}

func (e *DatabaseError) Error() string {
	return e.Message
}

// NewDatabaseError creates a new DatabaseError
func NewDatabaseError(message string, code string, statusCode int) *DatabaseError {
	return &DatabaseError{
		Message:    message,
		Code:       code,
		StatusCode: statusCode,
	}
}
