// Filename: internal/store/store.go

package store

import (
	"context"
	"errors"
	"time"
)

// ErrNotFound is returned when a key is not found in the store.
var ErrNotFound = errors.New("key not found")

// Message is the struct for received pub/sub messages.
type Message struct {
	Channel string
	Payload []byte
}

// Subscription represents an active subscription to a pub/sub channel.
type Subscription interface {
	Channel() <-chan *Message
	ChannelName() string
	Close() error
}

// Pipeliner defines an interface for executing a batch of commands.
type Pipeliner interface {
	// General
	Del(keys ...string)
	Expire(key string, expiration time.Duration)

	// HASH
	HSet(key string, values map[string]any)
	HIncrBy(key, field string, incr int64)

	// SET
	MSet(values map[string]any)
	Set(key string, value []byte, expiration time.Duration)
	SAdd(key string, members ...any)
	SRem(key string, members ...any)

	// LIST
	LPush(key string, values ...any)
	LRem(key string, count int64, value any)

	// ZSET
	ZAdd(key string, members map[string]float64)
	ZRem(key string, members ...any)

	// Execution
	Exec() error
}

// Store is the master interface for our cache service.
type Store interface {
	// Basic K/V operations
	Set(ctx context.Context, key string, value []byte, ttl time.Duration) error
	Get(ctx context.Context, key string) ([]byte, error)
	Del(ctx context.Context, keys ...string) error
	Exists(ctx context.Context, key string) (bool, error)
	SetNX(ctx context.Context, key string, value []byte, ttl time.Duration) (bool, error)
	MSet(ctx context.Context, values map[string]any) error

	// HASH operations
	HSet(ctx context.Context, key string, values map[string]any) error
	HGet(ctx context.Context, key, field string) (string, error)
	HGetAll(ctx context.Context, key string) (map[string]string, error)
	HIncrBy(ctx context.Context, key, field string, incr int64) (int64, error)
	HDel(ctx context.Context, key string, fields ...string) error

	// LIST operations
	LPush(ctx context.Context, key string, values ...any) error
	LRem(ctx context.Context, key string, count int64, value any) error
	Rotate(ctx context.Context, key string) (string, error)
	LIndex(ctx context.Context, key string, index int64) (string, error)
	Expire(ctx context.Context, key string, expiration time.Duration) error

	// SET operations
	SAdd(ctx context.Context, key string, members ...any) error
	SPopN(ctx context.Context, key string, count int64) ([]string, error)
	SMembers(ctx context.Context, key string) ([]string, error)
	SRem(ctx context.Context, key string, members ...any) error
	SRandMember(ctx context.Context, key string) (string, error)
	SUnionStore(ctx context.Context, destination string, keys ...string) (int64, error)

	// Pub/Sub operations
	Publish(ctx context.Context, channel string, message []byte) error
	Subscribe(ctx context.Context, channel string) (Subscription, error)

	// Pipeline
	Pipeline(ctx context.Context) Pipeliner

	// Close closes the store and releases any underlying resources.
	Close() error

	// ZSET operations
	ZAdd(ctx context.Context, key string, members map[string]float64) error
	ZRange(ctx context.Context, key string, start, stop int64) ([]string, error)
	ZRem(ctx context.Context, key string, members ...any) error
	PopAndCycleSetMember(ctx context.Context, mainKey, cooldownKey string) (string, error)
}
