package storage

import (
	"context"
	"time"

	"chorus.services/bzzz/pkg/ucxl"
	"chorus.services/bzzz/pkg/crypto"
	slurpContext "chorus.services/bzzz/pkg/slurp/context"
)

// ContextStore provides the main interface for context storage and retrieval
//
// This is the primary interface for storing, retrieving, and managing context
// data with support for both local and distributed storage, role-based access
// control, and efficient search capabilities.
type ContextStore interface {
	// StoreContext stores a context node with role-based encryption
	StoreContext(ctx context.Context, node *slurpContext.ContextNode, roles []string) error
	
	// RetrieveContext retrieves context for a UCXL address and role
	RetrieveContext(ctx context.Context, address ucxl.Address, role string) (*slurpContext.ContextNode, error)
	
	// UpdateContext updates an existing context node
	UpdateContext(ctx context.Context, node *slurpContext.ContextNode, roles []string) error
	
	// DeleteContext removes a context node from storage
	DeleteContext(ctx context.Context, address ucxl.Address) error
	
	// ExistsContext checks if context exists for an address
	ExistsContext(ctx context.Context, address ucxl.Address) (bool, error)
	
	// ListContexts lists contexts matching criteria
	ListContexts(ctx context.Context, criteria *ListCriteria) ([]*slurpContext.ContextNode, error)
	
	// SearchContexts searches contexts using query criteria
	SearchContexts(ctx context.Context, query *SearchQuery) (*SearchResults, error)
	
	// BatchStore stores multiple contexts efficiently
	BatchStore(ctx context.Context, batch *BatchStoreRequest) (*BatchStoreResult, error)
	
	// BatchRetrieve retrieves multiple contexts efficiently
	BatchRetrieve(ctx context.Context, batch *BatchRetrieveRequest) (*BatchRetrieveResult, error)
	
	// GetStorageStats returns storage statistics and health information
	GetStorageStats(ctx context.Context) (*StorageStatistics, error)
	
	// Sync synchronizes with distributed storage
	Sync(ctx context.Context) error
	
	// Backup creates a backup of stored contexts
	Backup(ctx context.Context, destination string) error
	
	// Restore restores contexts from backup
	Restore(ctx context.Context, source string) error
}

// LocalStorage provides local filesystem-based storage
type LocalStorage interface {
	// Store stores context data locally with optional encryption
	Store(ctx context.Context, key string, data interface{}, options *StoreOptions) error
	
	// Retrieve retrieves context data from local storage
	Retrieve(ctx context.Context, key string) (interface{}, error)
	
	// Delete removes data from local storage
	Delete(ctx context.Context, key string) error
	
	// Exists checks if data exists locally
	Exists(ctx context.Context, key string) (bool, error)
	
	// List lists all keys matching a pattern
	List(ctx context.Context, pattern string) ([]string, error)
	
	// Size returns the size of stored data
	Size(ctx context.Context, key string) (int64, error)
	
	// Compact compacts local storage to reclaim space
	Compact(ctx context.Context) error
	
	// GetLocalStats returns local storage statistics
	GetLocalStats() (*LocalStorageStats, error)
}

// DistributedStorage provides DHT-based distributed storage
type DistributedStorage interface {
	// Store stores data in the distributed DHT with replication
	Store(ctx context.Context, key string, data interface{}, options *DistributedStoreOptions) error
	
	// Retrieve retrieves data from the distributed DHT
	Retrieve(ctx context.Context, key string) (interface{}, error)
	
	// Delete removes data from the distributed DHT
	Delete(ctx context.Context, key string) error
	
	// Exists checks if data exists in the DHT
	Exists(ctx context.Context, key string) (bool, error)
	
	// Replicate ensures data is replicated across nodes
	Replicate(ctx context.Context, key string, replicationFactor int) error
	
	// FindReplicas finds all replicas of data
	FindReplicas(ctx context.Context, key string) ([]string, error)
	
	// Sync synchronizes with other DHT nodes
	Sync(ctx context.Context) error
	
	// GetDistributedStats returns distributed storage statistics
	GetDistributedStats() (*DistributedStorageStats, error)
}

// EncryptedStorage provides role-based encrypted storage
type EncryptedStorage interface {
	// StoreEncrypted stores data encrypted for specific roles
	StoreEncrypted(ctx context.Context, key string, data interface{}, roles []string) error
	
	// RetrieveDecrypted retrieves and decrypts data for current role
	RetrieveDecrypted(ctx context.Context, key string, role string) (interface{}, error)
	
	// CanAccess checks if a role can access specific data
	CanAccess(ctx context.Context, key string, role string) (bool, error)
	
	// ListAccessibleKeys lists keys accessible to a role
	ListAccessibleKeys(ctx context.Context, role string) ([]string, error)
	
	// ReEncryptForRoles re-encrypts data for different roles
	ReEncryptForRoles(ctx context.Context, key string, newRoles []string) error
	
	// GetAccessRoles gets roles that can access specific data
	GetAccessRoles(ctx context.Context, key string) ([]string, error)
	
	// RotateKeys rotates encryption keys
	RotateKeys(ctx context.Context, maxAge time.Duration) error
	
	// ValidateEncryption validates encryption integrity
	ValidateEncryption(ctx context.Context, key string) error
}

// CacheManager manages multi-level caching for performance
type CacheManager interface {
	// Get retrieves data from cache
	Get(ctx context.Context, key string) (interface{}, bool, error)
	
	// Set stores data in cache with TTL
	Set(ctx context.Context, key string, data interface{}, ttl time.Duration) error
	
	// Delete removes data from cache
	Delete(ctx context.Context, key string) error
	
	// DeletePattern removes cache entries matching pattern
	DeletePattern(ctx context.Context, pattern string) error
	
	// Clear clears all cache entries
	Clear(ctx context.Context) error
	
	// Warm pre-loads cache with frequently accessed data
	Warm(ctx context.Context, keys []string) error
	
	// GetCacheStats returns cache performance statistics
	GetCacheStats() (*CacheStatistics, error)
	
	// SetCachePolicy sets caching policy
	SetCachePolicy(policy *CachePolicy) error
}

// IndexManager manages search indexes for efficient querying
type IndexManager interface {
	// CreateIndex creates a search index for contexts
	CreateIndex(ctx context.Context, indexName string, config *IndexConfig) error
	
	// UpdateIndex updates search index with new data
	UpdateIndex(ctx context.Context, indexName string, key string, data interface{}) error
	
	// DeleteFromIndex removes data from search index
	DeleteFromIndex(ctx context.Context, indexName string, key string) error
	
	// Search searches indexed data using query
	Search(ctx context.Context, indexName string, query *SearchQuery) (*SearchResults, error)
	
	// RebuildIndex rebuilds search index from stored data
	RebuildIndex(ctx context.Context, indexName string) error
	
	// OptimizeIndex optimizes search index for performance
	OptimizeIndex(ctx context.Context, indexName string) error
	
	// GetIndexStats returns index statistics
	GetIndexStats(ctx context.Context, indexName string) (*IndexStatistics, error)
	
	// ListIndexes lists all available indexes
	ListIndexes(ctx context.Context) ([]string, error)
}

// BackupManager handles backup and recovery operations
type BackupManager interface {
	// CreateBackup creates a backup of stored data
	CreateBackup(ctx context.Context, config *BackupConfig) (*BackupInfo, error)
	
	// RestoreBackup restores data from backup
	RestoreBackup(ctx context.Context, backupID string, config *RestoreConfig) error
	
	// ListBackups lists available backups
	ListBackups(ctx context.Context) ([]*BackupInfo, error)
	
	// DeleteBackup removes a backup
	DeleteBackup(ctx context.Context, backupID string) error
	
	// ValidateBackup validates backup integrity
	ValidateBackup(ctx context.Context, backupID string) (*BackupValidation, error)
	
	// ScheduleBackup schedules automatic backups
	ScheduleBackup(ctx context.Context, schedule *BackupSchedule) error
	
	// GetBackupStats returns backup statistics
	GetBackupStats(ctx context.Context) (*BackupStatistics, error)
}

// TransactionManager provides ACID transaction support
type TransactionManager interface {
	// BeginTransaction starts a new transaction
	BeginTransaction(ctx context.Context) (*Transaction, error)
	
	// CommitTransaction commits a transaction
	CommitTransaction(ctx context.Context, tx *Transaction) error
	
	// RollbackTransaction rolls back a transaction
	RollbackTransaction(ctx context.Context, tx *Transaction) error
	
	// GetActiveTransactions returns list of active transactions
	GetActiveTransactions(ctx context.Context) ([]*Transaction, error)
}

// EventNotifier provides event notifications for storage operations
type EventNotifier interface {
	// NotifyStored notifies when data is stored
	NotifyStored(ctx context.Context, event *StorageEvent) error
	
	// NotifyRetrieved notifies when data is retrieved
	NotifyRetrieved(ctx context.Context, event *StorageEvent) error
	
	// NotifyUpdated notifies when data is updated
	NotifyUpdated(ctx context.Context, event *StorageEvent) error
	
	// NotifyDeleted notifies when data is deleted
	NotifyDeleted(ctx context.Context, event *StorageEvent) error
	
	// Subscribe subscribes to storage events
	Subscribe(ctx context.Context, eventType EventType, handler EventHandler) error
	
	// Unsubscribe unsubscribes from storage events
	Unsubscribe(ctx context.Context, eventType EventType, handler EventHandler) error
}

// Supporting types for storage operations

// EventType represents types of storage events
type EventType string

const (
	EventStored    EventType = "stored"
	EventRetrieved EventType = "retrieved"
	EventUpdated   EventType = "updated"
	EventDeleted   EventType = "deleted"
	EventSynced    EventType = "synced"
	EventBackedUp  EventType = "backed_up"
	EventRestored  EventType = "restored"
)

// EventHandler handles storage events
type EventHandler func(event *StorageEvent) error

// StorageEvent represents a storage operation event
type StorageEvent struct {
	Type      EventType                `json:"type"`       // Event type
	Key       string                   `json:"key"`        // Storage key
	Data      interface{}              `json:"data"`       // Event data
	Timestamp time.Time                `json:"timestamp"`  // When event occurred
	Metadata  map[string]interface{}   `json:"metadata"`   // Additional metadata
}

// Transaction represents a storage transaction
type Transaction struct {
	ID        string                   `json:"id"`         // Transaction ID
	StartTime time.Time                `json:"start_time"` // When transaction started
	Operations []*TransactionOperation `json:"operations"` // Transaction operations
	Status    TransactionStatus        `json:"status"`     // Transaction status
}

// TransactionOperation represents a single operation in a transaction
type TransactionOperation struct {
	Type      string                 `json:"type"`       // Operation type
	Key       string                 `json:"key"`        // Storage key
	Data      interface{}            `json:"data"`       // Operation data
	Metadata  map[string]interface{} `json:"metadata"`   // Operation metadata
}

// TransactionStatus represents transaction status
type TransactionStatus string

const (
	TransactionActive    TransactionStatus = "active"
	TransactionCommitted TransactionStatus = "committed"
	TransactionRolledBack TransactionStatus = "rolled_back"
	TransactionFailed    TransactionStatus = "failed"
)