package minio

import (
	"context"
	"io"
)

// Logger defines the interface for logging operations
type Logger interface {
	Info(message string, fields map[string]interface{})
	Error(message string, fields map[string]interface{})
	Debug(message string, fields map[string]interface{})
	Warn(message string, fields map[string]interface{})
}

// FileInfo represents file information
type FileInfo struct {
	Name         string            `json:"name"`
	Path         string            `json:"path"`
	Size         int64             `json:"size"`
	ContentType  string            `json:"contentType"`
	ETag         string            `json:"etag"`
	LastModified int64             `json:"lastModified"`
	Metadata     map[string]string `json:"metadata"`
}

// UploadOptions represents upload configuration
type UploadOptions struct {
	ContentType string            `json:"contentType"`
	Metadata    map[string]string `json:"metadata"`
}

// HierarchicalUploadOptions extends UploadOptions for hierarchical storage
type HierarchicalUploadOptions struct {
	UploadOptions
	Category    string `json:"category"`    // e.g., "contracts", "invoices", "reports"
	SubCategory string `json:"subCategory"` // e.g., "2024", "Q1"
	Tags        []string `json:"tags"`       // Additional classification tags
}

// DownloadOptions represents download configuration
type DownloadOptions struct {
	Range *DownloadRange `json:"range,omitempty"`
}

// DownloadRange represents a byte range for partial downloads
type DownloadRange struct {
	Start int64 `json:"start"`
	End   int64 `json:"end,omitempty"` // 0 means until end
}

// ListOptions represents listing configuration
type ListOptions struct {
	Prefix    string `json:"prefix"`
	Delimiter string `json:"delimiter"`
	MaxKeys   int32  `json:"maxKeys"`
	Marker    string `json:"marker"`
}

// ListResult represents the result of a list operation
type ListResult struct {
	Objects         []FileInfo `json:"objects"`
	CommonPrefixes  []string   `json:"commonPrefixes"`
	IsTruncated     bool       `json:"isTruncated"`
	NextMarker      string     `json:"nextMarker"`
}

// StorageType represents different storage types
type StorageType string

const (
	StorageTypeNormal      StorageType = "normal"      // For general files (images, videos, etc.)
	StorageTypeHierarchical StorageType = "hierarchical" // For documents with classification
)

// FileManager defines the interface for file operations
type FileManager interface {
	// Upload uploads a file to normal storage
	Upload(ctx context.Context, bucket, objectName string, reader io.Reader, options UploadOptions) error

	// UploadHierarchical uploads a file to hierarchical storage with classification
	UploadHierarchical(ctx context.Context, file io.Reader, filename string, options HierarchicalUploadOptions) (string, error)

	// Download downloads a file
	Download(ctx context.Context, bucket, objectName string, options DownloadOptions) (io.ReadCloser, error)

	// Delete deletes a file
	Delete(ctx context.Context, bucket, objectName string) error

	// GetInfo gets file information
	GetInfo(ctx context.Context, bucket, objectName string) (*FileInfo, error)

	// List lists files with optional prefix
	List(ctx context.Context, bucket string, options ListOptions) (*ListResult, error)

	// Copy copies a file within the same bucket or to another bucket
	Copy(ctx context.Context, srcBucket, srcObject, destBucket, destObject string) error

	// Move moves a file (copy + delete)
	Move(ctx context.Context, srcBucket, srcObject, destBucket, destObject string) error

	// Exists checks if a file exists
	Exists(ctx context.Context, bucket, objectName string) (bool, error)

	// GetPresignedURL generates a presigned URL for temporary access
	GetPresignedURL(ctx context.Context, bucket, objectName string, expirySeconds int64) (string, error)
}

// HierarchicalStorage defines the interface for hierarchical document storage
type HierarchicalStorage interface {
	// UploadDocument uploads a document with hierarchical classification
	UploadDocument(ctx context.Context, file io.Reader, filename string, options HierarchicalUploadOptions) (string, error)

	// ListDocuments lists documents in a category/subcategory
	ListDocuments(ctx context.Context, category, subCategory string, options ListOptions) (*ListResult, error)

	// GetDocumentPath generates the hierarchical path for a document
	GetDocumentPath(category, subCategory, filename string, tags []string) string

	// SearchDocuments searches documents by tags or metadata
	SearchDocuments(ctx context.Context, query string, category, subCategory string, options ListOptions) (*ListResult, error)
}

// BucketManager defines the interface for bucket operations
type BucketManager interface {
	// CreateBucket creates a new bucket
	CreateBucket(ctx context.Context, bucketName string) error

	// DeleteBucket deletes a bucket
	DeleteBucket(ctx context.Context, bucketName string) error

	// BucketExists checks if a bucket exists
	BucketExists(ctx context.Context, bucketName string) (bool, error)

	// ListBuckets lists all buckets
	ListBuckets(ctx context.Context) ([]string, error)

	// GetBucketInfo gets bucket information
	GetBucketInfo(ctx context.Context, bucketName string) (map[string]interface{}, error)
}

// ConnectionManagerInterface defines the interface for MinIO connection management
type ConnectionManagerInterface interface {
	// Connect establishes connection to MinIO
	Connect() error

	// Disconnect closes the connection
	Disconnect(ctx context.Context) error

	// Ping tests the connection
	Ping(ctx context.Context) error

	// IsConnected returns true if connected
	IsConnected() bool

	// GetClient returns the underlying MinIO client
	GetClient() interface{}

	// CreateBucket creates a new bucket
	CreateBucket(ctx context.Context, bucketName string) error

	// BucketExists checks if a bucket exists
	BucketExists(ctx context.Context, bucketName string) (bool, error)

	// ListBuckets lists all buckets
	ListBuckets(ctx context.Context) ([]string, error)
}
