// Copyright (C) 2025 wangyusong
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

// TODO: fix tests
package block

// import (
// 	// "context"
// 	"encoding/json"
// 	"os"
// 	"path/filepath"
// 	// "sync/atomic"
// 	"testing"
// 	"time"
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//

// 	// "github.com/benbjohnson/clock"
// 	. "github.com/onsi/gomega"
// 	"github.com/stretchr/testify/mock"

// 	"github.com/glidea/zenfeed/pkg/model"
// 	"github.com/glidea/zenfeed/pkg/storage/feed/block/chunk"
// 	// "github.com/glidea/zenfeed/pkg/storage/feed/block/index/inverted"
// 	// "github.com/glidea/zenfeed/pkg/storage/feed/block/index/primary"
// 	// "github.com/glidea/zenfeed/pkg/storage/feed/block/index/vector"
// 	"github.com/glidea/zenfeed/pkg/test"
// 	runtimeutil "github.com/glidea/zenfeed/pkg/util/runtime"
// )

// func TestNew(t *testing.T) {
// 	RegisterTestingT(t)

// 	t0 := time.Now()

// 	type givenDetail struct {
// 		setupDir     func(string) error
// 		config       *Config
// 		chunkMock    func(obj *mock.Mock)
// 		primaryMock  func(obj *mock.Mock)
// 		invertedMock func(obj *mock.Mock)
// 		vectorMock   func(obj *mock.Mock)
// 	}
// 	type whenDetail struct{}
// 	type thenExpected struct {
// 		state                       State
// 		chunkFactoryNewCallCount    int
// 		primaryFactoryNewCallCount  int
// 		invertedFactoryNewCallCount int
// 		vectorFactoryNewCallCount   int
// 		err                         string
// 	}

// 	tests := []test.Case[givenDetail, whenDetail, thenExpected]{
// 		{
// 			Scenario: "Creating new block with valid config",
// 			Given:    "A config with valid parameters",
// 			When:     "Calling New function",
// 			Then:     "Should create a new block successfully",
// 			GivenDetail: givenDetail{
// 				setupDir: func(dir string) error {
// 					return nil // No need to pre-setup, new directory will be created.
// 				},
// 				config: &Config{
// 					Dir:                     "", // Will be set to temp dir in test.
// 					Start:                   t0,
// 					Duration:                24 * time.Hour,
// 					SelectableEmbeddingLLMs: []EmbeddingLLM{{Name: "test", Start: time.Time{}}},
// 				},
// 			},
// 			ThenExpected: thenExpected{
// 				state:                       StateHot,
// 				chunkFactoryNewCallCount:    1,
// 				primaryFactoryNewCallCount:  1,
// 				invertedFactoryNewCallCount: 1,
// 				vectorFactoryNewCallCount:   1,
// 			},
// 		},
// 		{
// 			Scenario: "Recover hot block from disk",
// 			Given:    "Block data directory exists on disk and no archive metadata file",
// 			When:     "Calling New function",
// 			Then:     "Should recover block successfully",
// 			GivenDetail: givenDetail{
// 				setupDir: func(dir string) error {
// 					// Create chunk directory but not create archive.json.
// 					chunkDir := filepath.Join(dir, chunkDirname)
// 					if err := os.MkdirAll(chunkDir, 0755); err != nil {
// 						return err
// 					}
// 					if _, err := os.Create(filepath.Join(chunkDir, chunkFilename(0))); err != nil {
// 						return err
// 					}
// 					if _, err := os.Create(filepath.Join(chunkDir, chunkFilename(1))); err != nil {
// 						return err
// 					}
// 					return nil
// 				},
// 				chunkMock: func(obj *mock.Mock) {
// 					obj.On("Range", mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
// 						iter := args.Get(1).(func(feed *chunk.Feed, offset uint64) error)
// 						runtimeutil.Must(iter(&chunk.Feed{ID: 1, Vectors: [][]float32{{1, 2, 3}, {4, 5, 6}}, Feed: &model.Feed{Labels: model.Labels{model.Label{Key: "k1", Value: "v1"}}, Time: time.Date(2025, 3, 3, 0, 0, 0, 0, time.UTC)}}, 0))
// 						runtimeutil.Must(iter(&chunk.Feed{ID: 2, Vectors: [][]float32{{7, 8, 9}, {10, 11, 12}}, Feed: &model.Feed{Labels: model.Labels{model.Label{Key: "k2", Value: "v2"}}, Time: time.Date(2025, 5, 20, 0, 0, 0, 0, time.UTC)}}, 1))
// 					}).Return(nil) // Two chunk files.
// 				},
// 				primaryMock: func(obj *mock.Mock) {
// 					obj.On("Add", mock.Anything, uint64(1), primaryindex.FeedRef{Chunk: 0, Offset: 0, Time: time.Date(2025, 3, 3, 0, 0, 0, 0, time.UTC)}).Return(nil)
// 					obj.On("Add", mock.Anything, uint64(2), primaryindex.FeedRef{Chunk: 0, Offset: 1, Time: time.Date(2025, 5, 20, 0, 0, 0, 0, time.UTC)}).Return(nil)
// 					obj.On("Add", mock.Anything, uint64(1), primaryindex.FeedRef{Chunk: 1, Offset: 0, Time: time.Date(2025, 3, 3, 0, 0, 0, 0, time.UTC)}).Return(nil)
// 					obj.On("Add", mock.Anything, uint64(2), primaryindex.FeedRef{Chunk: 1, Offset: 1, Time: time.Date(2025, 5, 20, 0, 0, 0, 0, time.UTC)}).Return(nil)
// 				},
// 				invertedMock: func(obj *mock.Mock) {
// 					obj.On("Add", mock.Anything, uint64(1), model.Labels{model.Label{Key: "k1", Value: "v1"}}).Return(nil).Times(2) // Two chunk files.
// 					obj.On("Add", mock.Anything, uint64(2), model.Labels{model.Label{Key: "k2", Value: "v2"}}).Return(nil).Times(2)
// 				},
// 				vectorMock: func(obj *mock.Mock) {
// 					obj.On("Add", mock.Anything, uint64(1), [][]float32{{1, 2, 3}, {4, 5, 6}}).Return(nil).Times(2) // Two chunk files.
// 					obj.On("Add", mock.Anything, uint64(2), [][]float32{{7, 8, 9}, {10, 11, 12}}).Return(nil).Times(2)
// 				},
// 				config: &Config{
// 					Dir:                     "", // Will be set to temp dir in test.
// 					Start:                   t0,
// 					Retention:               7 * 24 * time.Hour,
// 					Duration:                24 * time.Hour,
// 					WriteableWindow:         48 * time.Hour, // Within this window.
// 					SelectableEmbeddingLLMs: []EmbeddingLLM{{Name: "test", Start: time.Time{}}},
// 				},
// 			},
// 			ThenExpected: thenExpected{
// 				state:                       StateHot,
// 				chunkFactoryNewCallCount:    2,
// 				primaryFactoryNewCallCount:  1,
// 				invertedFactoryNewCallCount: 1,
// 				vectorFactoryNewCallCount:   1,
// 			},
// 		},
// 		{
// 			Scenario: "Recover hot readonly block from disk",
// 			Given:    "Block data directory exists on disk and no archive metadata file, and WriteableWindow is out of range",
// 			When:     "Calling New function",
// 			Then:     "Should recover block successfully and state is hot readonly",
// 			GivenDetail: givenDetail{
// 				setupDir: func(dir string) error {
// 					// Create chunk directory but not create archive.json.
// 					chunkDir := filepath.Join(dir, chunkDirname)
// 					if err := os.MkdirAll(chunkDir, 0755); err != nil {
// 						return err
// 					}
// 					if _, err := os.Create(filepath.Join(chunkDir, chunkFilename(0))); err != nil {
// 						return err
// 					}
// 					if _, err := os.Create(filepath.Join(chunkDir, chunkFilename(1))); err != nil {
// 						return err
// 					}
// 					return nil
// 				},
// 				chunkMock: func(obj *mock.Mock) {
// 					obj.On("Range", mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
// 						iter := args.Get(1).(func(feed *chunk.Feed, offset uint64) error)
// 						runtimeutil.Must(iter(&chunk.Feed{ID: 1, Feed: &model.Feed{Labels: model.Labels{model.Label{Key: "k1", Value: "v1"}}, Time: time.Date(2025, 3, 3, 0, 0, 0, 0, time.UTC)}}, 0))
// 						runtimeutil.Must(iter(&chunk.Feed{ID: 2, Feed: &model.Feed{Labels: model.Labels{model.Label{Key: "k2", Value: "v2"}}, Time: time.Date(2025, 5, 20, 0, 0, 0, 0, time.UTC)}}, 1))
// 					}).Return(nil) // Two chunk files.
// 				},
// 				primaryMock: func(obj *mock.Mock) {
// 					obj.On("Add", mock.Anything, uint64(1), primaryindex.FeedRef{Chunk: 0, Offset: 0, Time: time.Date(2025, 3, 3, 0, 0, 0, 0, time.UTC)}).Return(nil)
// 					obj.On("Add", mock.Anything, uint64(2), primaryindex.FeedRef{Chunk: 0, Offset: 1, Time: time.Date(2025, 5, 20, 0, 0, 0, 0, time.UTC)}).Return(nil)
// 					obj.On("Add", mock.Anything, uint64(1), primaryindex.FeedRef{Chunk: 1, Offset: 0, Time: time.Date(2025, 3, 3, 0, 0, 0, 0, time.UTC)}).Return(nil)
// 					obj.On("Add", mock.Anything, uint64(2), primaryindex.FeedRef{Chunk: 1, Offset: 1, Time: time.Date(2025, 5, 20, 0, 0, 0, 0, time.UTC)}).Return(nil)
// 				},
// 				invertedMock: func(obj *mock.Mock) {
// 					obj.On("Add", mock.Anything, uint64(1), model.Labels{model.Label{Key: "k1", Value: "v1"}}).Return(nil).Times(2) // Two chunk files.
// 					obj.On("Add", mock.Anything, uint64(2), model.Labels{model.Label{Key: "k2", Value: "v2"}}).Return(nil).Times(2)
// 				},
// 				vectorMock: func(obj *mock.Mock) {
// 					obj.On("Add", mock.Anything, uint64(1), [][]float32{{1, 2, 3}, {4, 5, 6}}).Return(nil).Times(2) // Two chunk files.
// 					obj.On("Add", mock.Anything, uint64(2), [][]float32{{7, 8, 9}, {10, 11, 12}}).Return(nil).Times(2)
// 				},
// 				config: &Config{
// 					Dir:                     "", // Will be set to temp dir in test.
// 					Start:                   t0.Add(-72 * time.Hour),
// 					Retention:               7 * 24 * time.Hour,
// 					Duration:                24 * time.Hour,
// 					WriteableWindow:         25 * time.Hour,
// 					SelectableEmbeddingLLMs: []EmbeddingLLM{{Name: "test", Start: time.Time{}}},
// 				},
// 			},
// 			ThenExpected: thenExpected{
// 				state:                       StateHotReadonly,
// 				chunkFactoryNewCallCount:    2,
// 				primaryFactoryNewCallCount:  1,
// 				invertedFactoryNewCallCount: 1,
// 				vectorFactoryNewCallCount:   1,
// 			},
// 		},
// 		{
// 			Scenario: "Recover cold block from disk",
// 			Given:    "Block data directory exists on disk and has archive metadata file",
// 			When:     "Calling New function",
// 			Then:     "Should recover block successfully as cold state",
// 			GivenDetail: givenDetail{
// 				setupDir: func(dir string) error {
// 					// Create block directory structure with archive.json
// 					chunkDir := filepath.Join(dir, chunkDirname)
// 					if err := os.MkdirAll(chunkDir, 0755); err != nil {
// 						return err
// 					}

// 					// Create chunk files
// 					if _, err := os.Create(filepath.Join(chunkDir, chunkFilename(0))); err != nil {
// 						return err
// 					}
// 					if _, err := os.Create(filepath.Join(chunkDir, chunkFilename(1))); err != nil {
// 						return err
// 					}

// 					// Create archive.json to indicate cold state
// 					meta := archiveMetadata{FeedCount: 4}
// 					bs := runtimeutil.Must1(json.Marshal(meta))
// 					if err := os.WriteFile(filepath.Join(dir, archiveMetaFilename), bs, 0644); err != nil {
// 						return err
// 					}

// 					// Create index directory and files
// 					indexDir := filepath.Join(dir, indexDirname)
// 					if err := os.MkdirAll(indexDir, 0755); err != nil {
// 						return err
// 					}
// 					for _, name := range []string{indexPrimaryFilename, indexInvertedFilename, indexVectorFilename} {
// 						if _, err := os.Create(filepath.Join(indexDir, name)); err != nil {
// 							return err
// 						}
// 					}
// 					return nil
// 				},
// 				chunkMock: func(obj *mock.Mock) {
// 					// No chunk mock needed since cold block doesn't load chunks initially
// 				},
// 				primaryMock: func(obj *mock.Mock) {
// 					// No primary mock needed since cold block doesn't load indices initially
// 				},
// 				invertedMock: func(obj *mock.Mock) {
// 					// No inverted mock needed since cold block doesn't load indices initially
// 				},
// 				vectorMock: func(obj *mock.Mock) {
// 					// No vector mock needed since cold block doesn't load indices initially
// 				},
// 				config: &Config{
// 					Dir:                     "", // Will be set to temp dir in test
// 					Start:                   t0,
// 					Retention:               7 * 24 * time.Hour,
// 					Duration:                24 * time.Hour,
// 					WriteableWindow:         48 * time.Hour,
// 					SelectableEmbeddingLLMs: []EmbeddingLLM{{Name: "test", Start: time.Time{}}},
// 				},
// 			},
// 			ThenExpected: thenExpected{
// 				state:                       StateCold,
// 				chunkFactoryNewCallCount:    0, // Cold block doesn't load chunks initially
// 				primaryFactoryNewCallCount:  1,
// 				invertedFactoryNewCallCount: 1,
// 				vectorFactoryNewCallCount:   1,
// 			},
// 		},
// 		{
// 			Scenario: "Creating new block - invalid config - missing SelectableEmbeddingLLMs",
// 			Given:    "A config with missing SelectableEmbeddingLLMs",
// 			When:     "Calling New function",
// 			Then:     "Should return an error",
// 			GivenDetail: givenDetail{
// 				config: &Config{
// 					Dir:      "", // Will be set to temp dir in test.
// 					Start:    t0,
// 					Duration: 24 * time.Hour,
// 				},
// 			},
// 			ThenExpected: thenExpected{
// 				err: "selectable embedding LLMs is required",
// 			},
// 		},
// 	}

// 	for _, tt := range tests {
// 		t.Run(tt.Scenario, func(t *testing.T) {
// 			// Given.
// 			tempDir, err := os.MkdirTemp("", "block_test_*")
// 			Expect(err).NotTo(HaveOccurred())
// 			defer os.RemoveAll(tempDir)

// 			// Set parent directory of config.
// 			if tt.GivenDetail.config != nil && tt.GivenDetail.config.Dir == "" {
// 				tt.GivenDetail.config.Dir = tempDir
// 			}

// 			// Execute setup of test scenario.
// 			if tt.GivenDetail.setupDir != nil {
// 				err := tt.GivenDetail.setupDir(tempDir)
// 				Expect(err).NotTo(HaveOccurred())
// 			}

// 			// Create mock factory.
// 			chunkFactoryNewCallCount := 0
// 			mockChunkFactory := chunk.NewFactory(func(obj *mock.Mock) {
// 				if tt.GivenDetail.chunkMock != nil {
// 					tt.GivenDetail.chunkMock(obj)
// 				}
// 				chunkFactoryNewCallCount++
// 			})
// 			primaryFactoryNewCallCount := 0
// 			mockPrimaryFactory := primaryindex.NewFactory(func(obj *mock.Mock) {
// 				if tt.GivenDetail.primaryMock != nil {
// 					tt.GivenDetail.primaryMock(obj)
// 				}
// 				primaryFactoryNewCallCount++
// 			})
// 			invertedFactoryNewCallCount := 0
// 			mockInvertedFactory := invertedindex.NewFactory(func(obj *mock.Mock) {
// 				if tt.GivenDetail.invertedMock != nil {
// 					tt.GivenDetail.invertedMock(obj)
// 				}
// 				invertedFactoryNewCallCount++
// 			})
// 			vectorFactoryNewCallCount := 0
// 			mockVectorFactory := vectorindex.NewFactory(func(obj *mock.Mock) {
// 				if tt.GivenDetail.vectorMock != nil {
// 					tt.GivenDetail.vectorMock(obj)
// 				}
// 				vectorFactoryNewCallCount++
// 			})

// 			// When.
// 			b, err := new("test", tt.GivenDetail.config, Dependencies{
// 				ChunkFactory:    mockChunkFactory,
// 				PrimaryFactory:  mockPrimaryFactory,
// 				InvertedFactory: mockInvertedFactory,
// 				VectorFactory:   mockVectorFactory,
// 			})

// 			// Then.
// 			if tt.ThenExpected.err != "" {
// 				Expect(err).To(HaveOccurred())
// 				Expect(err.Error()).To(ContainSubstring(tt.ThenExpected.err))
// 			} else {
// 				Expect(err).NotTo(HaveOccurred())
// 				Expect(b).NotTo(BeNil())

// 				// Validate self properties.
// 				rb := b.(*block)
// 				Expect(rb.state.Load().(State)).To(Equal(tt.ThenExpected.state))
// 				Expect(rb.chunks).To(HaveLen(tt.ThenExpected.chunkFactoryNewCallCount))

// 				// Validate dependencies.
// 				Expect(chunkFactoryNewCallCount).To(Equal(tt.ThenExpected.chunkFactoryNewCallCount))
// 				Expect(primaryFactoryNewCallCount).To(Equal(tt.ThenExpected.primaryFactoryNewCallCount))
// 				Expect(invertedFactoryNewCallCount).To(Equal(tt.ThenExpected.invertedFactoryNewCallCount))
// 				Expect(vectorFactoryNewCallCount).To(Equal(tt.ThenExpected.vectorFactoryNewCallCount))
// 				if tt.GivenDetail.config != nil {
// 					chunkDir := filepath.Join(tt.GivenDetail.config.Dir, chunkDirname)
// 					stat, err := os.Stat(chunkDir)
// 					Expect(err).NotTo(HaveOccurred())
// 					Expect(stat.IsDir()).To(BeTrue())
// 				}
// 			}
// 		})
// 	}
// }

// // func TestRun(t *testing.T) {
// // 	RegisterTestingT(t)

// // 	t0 := time.Date(2025, 3, 3, 0, 0, 0, 0, time.UTC)

// // 	type givenDetail struct {
// // 		config       *Config
// // 		initialState State
// // 		setup        func(b *block, mockClock *clock.Mock)
// // 	}
// // 	type whenDetail struct{}
// // 	type thenExpected struct {
// // 		state         State
// // 		chunksLen     int
// // 		chunksNil     bool
// // 		primaryNil    bool
// // 		invertedNil   bool
// // 		vectorNil     bool
// // 		archiveExists bool
// // 	}

// // 	tests := []test.Case[givenDetail, whenDetail, thenExpected]{
// // 		{
// // 			Scenario: "Hot to HotReadonly transition",
// // 			Given:    "A hot block that is about to exceed its writeable window",
// // 			When:     "Running the block",
// // 			Then:     "Should transition to hot-readonly state",
// // 			GivenDetail: givenDetail{
// // 				config: &Config{
// // 					Dir:             "/tmp", // Use Dir instead of ParentDir
// // 					Start:           t0,
// // 					Duration:        24 * time.Hour,
// // 					WriteableWindow: 48 * time.Hour,
// // 				},
// // 				initialState: StateHot,
// // 				setup: func(b *block, mockClock *clock.Mock) {
// // 					mockClock.Set(t0.Add(49 * time.Hour)) // Past writeable window.
// // 				},
// // 			},
// // 			ThenExpected: thenExpected{
// // 				state: StateHotReadonly,
// // 			},
// // 		},
// // 		{
// // 			Scenario: "HotReadonly to Hot transition",
// // 			Given:    "A hot-readonly block with a new, wider writeable window",
// // 			When:     "Running the block",
// // 			Then:     "Should transition to hot state and add a new chunk",
// // 			GivenDetail: givenDetail{
// // 				config: &Config{
// // 					Dir:             "/tmp", // Use Dir instead of ParentDir
// // 					Start:           t0,
// // 					Duration:        24 * time.Hour,
// // 					WriteableWindow: 48 * time.Hour,
// // 				},
// // 				initialState: StateHotReadonly,
// // 				setup: func(b *block, mockClock *clock.Mock) {
// // 					mockClock.Set(t0.Add(47 * time.Hour))
// // 				},
// // 			},
// // 			ThenExpected: thenExpected{
// // 				state:     StateHot,
// // 				chunksLen: 2 + 1, // Add 1 chunk when rollback to Hot.
// // 			},
// // 		},
// // 		{
// // 			Scenario: "HotReadonly to Cold transition",
// // 			Given:    "A hot-readonly block with no recent data access",
// // 			When:     "Running the block",
// // 			Then:     "Should transition to cold state and release resources",
// // 			GivenDetail: givenDetail{
// // 				config: &Config{
// // 					Dir:             "/tmp", // Use Dir instead of ParentDir
// // 					Start:           t0.Add(-49 * time.Hour),
// // 					Duration:        24 * time.Hour,
// // 					WriteableWindow: 48 * time.Hour,
// // 				},
// // 				initialState: StateHotReadonly,
// // 				setup: func(b *block, mockClock *clock.Mock) {
// // 					b.lastDataAccess.Store(t0)
// // 					mockClock.Set(t0.Add(6 * time.Minute)) // Past colding window (5 minutes)
// // 				},
// // 			},
// // 			ThenExpected: thenExpected{
// // 				state:       StateCold,
// // 				chunksNil:   true,
// // 				primaryNil:  true,
// // 				invertedNil: true,
// // 				vectorNil:   true,
// // 			},
// // 		},
// // 		{
// // 			Scenario: "ColdLoaded to Cold transition",
// // 			Given:    "A cold-loaded block with no recent data access",
// // 			When:     "Running the block",
// // 			Then:     "Should transition to cold state and release resources",
// // 			GivenDetail: givenDetail{
// // 				config: &Config{
// // 					Dir:             "/tmp", // Use Dir instead of ParentDir
// // 					Start:           t0,
// // 					Duration:        24 * time.Hour,
// // 					WriteableWindow: 48 * time.Hour,
// // 				},
// // 				initialState: StateColdLoaded,
// // 				setup: func(b *block, mockClock *clock.Mock) {
// // 					b.lastDataAccess.Store(t0)
// // 					mockClock.Set(t0.Add(6 * time.Minute)) // Past colding window (5 minutes)
// // 				},
// // 			},
// // 			ThenExpected: thenExpected{
// // 				state:       StateCold,
// // 				chunksNil:   true,
// // 				primaryNil:  true,
// // 				invertedNil: true,
// // 				vectorNil:   true,
// // 			},
// // 		},
// // 		{
// // 			Scenario: "Hot to ColdExpired transition",
// // 			Given:    "A hot block exceeding retention period",
// // 			When:     "Running the block",
// // 			Then:     "Should transition to ColdExpired state and create archive file",
// // 			GivenDetail: givenDetail{
// // 				config: &Config{
// // 					Dir:             "/tmp", // Use Dir instead of ParentDir
// // 					Start:           t0.Add(-8 * 24 * time.Hour),
// // 					Duration:        24 * time.Hour,
// // 					WriteableWindow: 48 * time.Hour,
// // 					Retention:       7 * 24 * time.Hour,
// // 				},
// // 				initialState: StateHot,
// // 				setup: func(b *block, mockClock *clock.Mock) {
// // 					mockClock.Set(t0)
// // 				},
// // 			},
// // 			ThenExpected: thenExpected{
// // 				state:         StateColdExpired,
// // 				archiveExists: true,
// // 			},
// // 		},
// // 	}

// // 	for _, tt := range tests {
// // 		t.Run(tt.Scenario, func(t *testing.T) {
// // 			// Given.

// // 			// Setup mock clock
// // 			mockClock := clock.NewMock()
// // 			clk = mockClock

// // 			// Create test block
// // 			chunkFactory := chunk.NewFactory(func(obj *mock.Mock) {
// // 				obj.On("EnsureReadonly").Return(nil).Times(2)
// // 				obj.On("Close").Return(nil).Times(3) // Max 3 chunks (2 initial + 1 possible new)
// // 			})
// // 			chunk1, err := chunkFactory.New(&chunk.Config{})
// // 			Expect(err).NotTo(HaveOccurred())
// // 			chunk2, err := chunkFactory.New(&chunk.Config{})
// // 			Expect(err).NotTo(HaveOccurred())
// // 			primaryFactory := primaryindex.NewFactory(func(obj *mock.Mock) {
// // 				obj.On("EncodeTo", mock.Anything).Return(nil)
// // 				obj.On("Count").Return(uint32(4))
// // 				obj.On("Close").Return(nil)
// // 			})
// // 			invertedFactory := invertedindex.NewFactory(func(obj *mock.Mock) {
// // 				obj.On("EncodeTo", mock.Anything).Return(nil)
// // 				obj.On("Close").Return(nil)
// // 			})
// // 			vectorFactory := vectorindex.NewFactory(func(obj *mock.Mock) {
// // 				obj.On("EncodeTo", mock.Anything).Return(nil)
// // 				obj.On("Close").Return(nil)
// // 			})

// // 			// Create a temporary directory for testing
// // 			tempDir, err := os.MkdirTemp("", "block_run_test")
// // 			Expect(err).NotTo(HaveOccurred())
// // 			defer os.RemoveAll(tempDir)

// // 			// Update the config to use the temporary directory
// // 			config := tt.GivenDetail.config
// // 			config.Dir = tempDir

// // 			ctx, cancel := context.WithCancel(context.Background())
// // 			b := &block{
// // 				ctx:           ctx,
// // 				cancel:        cancel,
// // 				chunks:        chunkChain{chunk1, chunk2},
// // 				blockDirpath:  filepath.Join(tempDir, blockDirname(config.Start, config.Start.Add(config.Duration))),
// // 				indexDirpath:  filepath.Join(tempDir, blockDirname(config.Start, config.Start.Add(config.Duration)), indexDirname),
// // 				chunkDirpath:  filepath.Join(tempDir, blockDirname(config.Start, config.Start.Add(config.Duration)), chunkDirname),
// // 				chunkFactory:  chunkFactory,
// // 				primaryIndex:  primaryFactory.New(),
// // 				invertedIndex: invertedFactory.New(),
// // 				vectorIndex:   vectorFactory.New(),
// // 				config:        atomic.Pointer[Config]{},
// // 			}
// // 			b.config.Store(config)
// // 			b.state.Store(tt.GivenDetail.initialState)

// // 			// Setup test scenario
// // 			if tt.GivenDetail.setup != nil {
// // 				tt.GivenDetail.setup(b, mockClock)
// // 			}

// // 			// When.

// // 			// Run block in goroutine.
// // 			done := make(chan error)
// // 			go func() {
// // 				done <- b.Run()
// // 			}()

// // 			// Wait for state transition.
// // 			time.Sleep(100 * time.Millisecond)
// // 			clk.(*clock.Mock).Add(35 * time.Second) // Wait tick

// // 			// Then.

// // 			// Verify state.
// // 			Expect(b.state.Load()).To(Equal(tt.ThenExpected.state))

// // 			if tt.ThenExpected.chunksLen > 0 {
// // 				Expect(b.chunks).To(HaveLen(tt.ThenExpected.chunksLen))
// // 			}
// // 			if tt.ThenExpected.chunksNil {
// // 				Expect(b.chunks).To(BeNil())
// // 			}
// // 			if tt.ThenExpected.primaryNil {
// // 				Expect(b.primaryIndex).To(BeNil())
// // 			}
// // 			if tt.ThenExpected.invertedNil {
// // 				Expect(b.invertedIndex).To(BeNil())
// // 			}
// // 			if tt.ThenExpected.vectorNil {
// // 				Expect(b.vectorIndex).To(BeNil())
// // 			}
// // 			if tt.ThenExpected.archiveExists {
// // 				archivePath := filepath.Join(b.blockDirpath, archiveMetaFilename)
// // 				_, err := os.Stat(archivePath)
// // 				Expect(err).NotTo(HaveOccurred()) // Check archive file exists
// // 			}

// // 			// Cleanup.
// // 			b.cancel()
// // 			err = <-done
// // 			Expect(err).NotTo(HaveOccurred())
// // 		})
// // 	}
// // }

// // func TestReload(t *testing.T) {
// // 	RegisterTestingT(t)

// // 	t0 := time.Date(2025, 3, 3, 0, 0, 0, 0, time.UTC)
// // 	tests := []struct {
// // 		scenario    string
// // 		given       string
// // 		when        string
// // 		then        string
// // 		initialCfg  *Config
// // 		reloadCfg   *Config
// // 		expectedErr string
// // 	}{
// // 		{
// // 			scenario: "Successful reload with mutable fields",
// // 			given:    "a block with initial config",
// // 			when:     "reloading with valid changes to mutable fields",
// // 			then:     "should accept the new config",
// // 			initialCfg: &Config{
// // 				ParentDir:       "/tmp",
// // 				BlockDirname:    blockDirname(t0, t0.Add(24*time.Hour)),
// // 				Start:           t0,
// // 				Duration:        24 * time.Hour,
// // 				WriteableWindow: 48 * time.Hour,
// // 				Retention:       7 * 24 * time.Hour,
// // 			},
// // 			reloadCfg: &Config{
// // 				WriteableWindow: 72 * time.Hour,      // Changed
// // 				Retention:       10 * 24 * time.Hour, // Changed
// // 			},
// // 		},
// // 		{
// // 			scenario: "Attempt to change ParentDir",
// // 			given:    "a block with initial config",
// // 			when:     "trying to change ParentDir",
// // 			then:     "should reject the change",
// // 			initialCfg: &Config{
// // 				ParentDir:    "/tmp",
// // 				BlockDirname: blockDirname(t0, t0.Add(24*time.Hour)),
// // 				Start:        t0,
// // 				Duration:     24 * time.Hour,
// // 			},
// // 			reloadCfg: &Config{
// // 				ParentDir: "/new/path",
// // 			},
// // 			expectedErr: "cannot reload the parent dir, MUST pass the same dir, or set it to empty for unchange",
// // 		},
// // 		{
// // 			scenario: "Attempt to change BlockDirname",
// // 			given:    "a block with initial config",
// // 			when:     "trying to change BlockDirname",
// // 			then:     "should reject the change",
// // 			initialCfg: &Config{
// // 				ParentDir:    "/tmp",
// // 				BlockDirname: blockDirname(t0, t0.Add(24*time.Hour)),
// // 				Start:        t0,
// // 				Duration:     24 * time.Hour,
// // 			},
// // 			reloadCfg: &Config{
// // 				BlockDirname: blockDirname(t0.Add(24*time.Hour), t0.Add(48*time.Hour)),
// // 			},
// // 			expectedErr: "cannot reload the block dirname, MUST pass the same dirname, or set it to empty for unchange",
// // 		},
// // 		{
// // 			scenario: "Attempt to change Start time",
// // 			given:    "a block with initial config",
// // 			when:     "trying to change Start time",
// // 			then:     "should reject the change",
// // 			initialCfg: &Config{
// // 				ParentDir:    "/tmp",
// // 				BlockDirname: blockDirname(t0, t0.Add(24*time.Hour)),
// // 				Start:        t0,
// // 				Duration:     24 * time.Hour,
// // 			},
// // 			reloadCfg: &Config{
// // 				Start: t0.Add(24 * time.Hour),
// // 			},
// // 			expectedErr: "cannot reload the start time, MUST pass the same start time, or set it to empty for unchange",
// // 		},
// // 		{
// // 			scenario: "Attempt to change Duration",
// // 			given:    "a block with initial config",
// // 			when:     "trying to change Duration",
// // 			then:     "should reject the change",
// // 			initialCfg: &Config{
// // 				ParentDir:    "/tmp",
// // 				BlockDirname: blockDirname(t0, t0.Add(24*time.Hour)),
// // 				Start:        t0,
// // 				Duration:     24 * time.Hour,
// // 			},
// // 			reloadCfg: &Config{
// // 				Duration: 48 * time.Hour,
// // 			},
// // 			expectedErr: "cannot reload the duration, MUST pass the same duration, or set it to empty for unchange",
// // 		},
// // 		{
// // 			scenario: "Invalid config validation",
// // 			given:    "a block with initial config",
// // 			when:     "trying to reload with invalid config",
// // 			then:     "should reject the change",
// // 			initialCfg: &Config{
// // 				ParentDir:       "/tmp",
// // 				BlockDirname:    blockDirname(t0, t0.Add(24*time.Hour)),
// // 				Start:           t0,
// // 				Duration:        24 * time.Hour,
// // 				WriteableWindow: 48 * time.Hour,
// // 				Retention:       7 * 24 * time.Hour,
// // 			},
// // 			reloadCfg: &Config{
// // 				WriteableWindow: 1 * time.Hour, // Invalid: less than Duration
// // 			},
// // 			expectedErr: "validate config: writeable window must be greater than 24h0m0s",
// // 		},
// // 		{
// // 			scenario: "Concurrent reload attempt",
// // 			given:    "a block that is already reloading",
// // 			when:     "trying to reload again",
// // 			then:     "should reject the concurrent reload",
// // 			initialCfg: &Config{
// // 				ParentDir:    "/tmp",
// // 				BlockDirname: blockDirname(t0, t0.Add(24*time.Hour)),
// // 				Start:        t0,
// // 				Duration:     24 * time.Hour,
// // 			},
// // 			reloadCfg: &Config{
// // 				WriteableWindow: 72 * time.Hour,
// // 			},
// // 			expectedErr: "concurrent reloading is forbidden",
// // 		},
// // 	}

// // 	for _, tt := range tests {
// // 		t.Run(tt.scenario, func(t *testing.T) {
// // 			// Create block with initial config
// // 			b := &block{
// // 				config:                atomic.Value{},
// // 				newConfigToReload:     make(chan *Config, 1),
// // 				newConfigReloadResult: make(chan error, 1),
// // 			}
// // 			b.config.Store(tt.initialCfg)

// // 			// For concurrent reload test
// // 			if tt.expectedErr == "concurrent reloading is forbidden" {
// // 				b.reloading.Store(true)
// // 			}

// // 			// Setup goroutine to handle reload request for successful cases
// // 			if tt.expectedErr == "" {
// // 				go func() {
// // 					cfg := <-b.newConfigToReload
// // 					// Verify the config was properly merged
// // 					Expect(cfg.ParentDir).To(Equal(tt.initialCfg.ParentDir))
// // 					Expect(cfg.BlockDirname).To(Equal(tt.initialCfg.BlockDirname))
// // 					Expect(cfg.Start).To(Equal(tt.initialCfg.Start))
// // 					Expect(cfg.Duration).To(Equal(tt.initialCfg.Duration))
// // 					if tt.reloadCfg.WriteableWindow != 0 {
// // 						Expect(cfg.WriteableWindow).To(Equal(tt.reloadCfg.WriteableWindow))
// // 					}
// // 					if tt.reloadCfg.Retention != 0 {
// // 						Expect(cfg.Retention).To(Equal(tt.reloadCfg.Retention))
// // 					}
// // 					b.config.Store(cfg)
// // 					b.newConfigReloadResult <- nil
// // 				}()
// // 			}

// // 			// Execute test
// // 			err := b.Reload(tt.reloadCfg)

// // 			// Verify results
// // 			if tt.expectedErr != "" {
// // 				Expect(err).To(HaveOccurred())
// // 				Expect(err.Error()).To(ContainSubstring(tt.expectedErr))
// // 			} else {
// // 				Expect(err).NotTo(HaveOccurred())

// // 				// Verify config was updated for successful cases
// // 				newConfig := b.config.Load().(*Config)
// // 				if tt.reloadCfg.WriteableWindow != 0 {
// // 					Expect(newConfig.WriteableWindow).To(Equal(tt.reloadCfg.WriteableWindow))
// // 				}
// // 				if tt.reloadCfg.Retention != 0 {
// // 					Expect(newConfig.Retention).To(Equal(tt.reloadCfg.Retention))
// // 				}
// // 			}
// // 		})
// // 	}
// // }

// // func TestAppend(t *testing.T) {
// // 	RegisterTestingT(t)

// // 	t0 := time.Date(2025, 3, 3, 0, 0, 0, 0, time.UTC)
// // 	clk = clock.NewMock()
// // 	clk.(*clock.Mock).Set(t0)

// // 	tests := []struct {
// // 		scenario           string
// // 		given              string
// // 		when               string
// // 		then               string
// // 		state              State
// // 		setupChunkMocks    func(chunkMock *mock.Mock)
// // 		setupPrimaryMocks  func(primaryMock *mock.Mock)
// // 		setupInvertedMocks func(invertedMock *mock.Mock)
// // 		setupVectorMocks   func(vectorMock *mock.Mock)
// // 		feeds              []*chunk.Feed
// // 		expectedErr        string
// // 	}{
// // 		{
// // 			scenario: "Successfully append feeds to hot block",
// // 			given:    "a hot block",
// // 			when:     "appending feeds",
// // 			then:     "should write to chunk and update indices",
// // 			state:    StateHot,
// // 			setupChunkMocks: func(chunkMock *mock.Mock) {
// // 				chunkMock.On("Count").Return(uint32(0))
// // 				chunkMock.On("Append", mock.Anything, mock.Anything).Return(nil).Run(func(args mock.Arguments) {
// // 					feeds := args.Get(0).([]*chunk.Feed)
// // 					callback := args.Get(1).(func(*chunk.Feed, uint64))
// // 					for i, feed := range feeds {
// // 						callback(feed, uint64(i))
// // 					}
// // 				})
// // 			},
// // 			setupPrimaryMocks: func(primaryMock *mock.Mock) {
// // 				primaryMock.On("Add", uint64(1), primaryindex.FeedRef{
// // 					Chunk:  0,
// // 					Offset: 0,
// // 					Time:   t0,
// // 				}).Return(nil)
// // 			},
// // 			setupInvertedMocks: func(invertedMock *mock.Mock) {
// // 				invertedMock.On("Add", uint64(1), model.Labels{model.Label{Key: "k1", Value: "v1"}}).Return(nil)
// // 			},
// // 			setupVectorMocks: func(vectorMock *mock.Mock) {
// // 				vectorMock.On("Add", uint64(1), [][]float32{{1, 2, 3}}).Return(nil)
// // 			},
// // 			feeds: []*chunk.Feed{
// // 				{
// // 					ID:      1,
// // 					Labels:  model.Labels{model.Label{Key: "k1", Value: "v1"}},
// // 					Vectors: [][]float32{{1, 2, 3}},
// // 					Time:    t0,
// // 				},
// // 			},
// // 		},
// // 		{
// // 			scenario:    "Append to non-hot block",
// // 			given:       "a hot-readonly block",
// // 			when:        "appending feeds",
// // 			then:        "should return error",
// // 			state:       StateHotReadonly,
// // 			feeds:       []*chunk.Feed{{ID: 1}},
// // 			expectedErr: "block is not writable",
// // 		},
// // 		{
// // 			scenario: "Create new chunk when current is full",
// // 			given:    "a hot block with chunk near capacity",
// // 			when:     "appending feeds that would exceed capacity",
// // 			then:     "should create new chunk and write to it",
// // 			state:    StateHot,
// // 			setupChunkMocks: func(chunkMock *mock.Mock) {
// // 				chunkMock.On("Count").Return(uint32(estimatedChunkFeedsLimit)).Twice()
// // 				chunkMock.On("EnsureReadonly").Return(nil).Once()
// // 				chunkMock.On("Append", mock.Anything, mock.Anything).Return(nil).Once()
// // 			},
// // 			setupPrimaryMocks: func(primaryMock *mock.Mock) {
// // 				primaryMock.On("Add", uint64(1), primaryindex.FeedRef{
// // 					Chunk:  0,
// // 					Offset: 0,
// // 					Time:   t0,
// // 				}).Return(nil)
// // 			},
// // 			setupInvertedMocks: func(invertedMock *mock.Mock) {
// // 				invertedMock.On("Add", uint64(1), model.Labels{model.Label{Key: "k1", Value: "v1"}}).Return(nil)
// // 			},
// // 			setupVectorMocks: func(vectorMock *mock.Mock) {
// // 				vectorMock.On("Add", uint64(1), [][]float32{{1, 2, 3}}).Return(nil)
// // 			},
// // 			feeds: []*chunk.Feed{
// // 				{
// // 					ID:      1,
// // 					Labels:  model.Labels{model.Label{Key: "k1", Value: "v1"}},
// // 					Vectors: [][]float32{{1, 2, 3}},
// // 					Time:    t0,
// // 				},
// // 			},
// // 		},
// // 	}

// // 	for _, tt := range tests {
// // 		t.Run(tt.scenario, func(t *testing.T) {
// // 			// Create mock factories
// // 			chunkFactory := chunk.NewFactory(func(obj *mock.Mock) {
// // 				if tt.setupChunkMocks != nil {
// // 					tt.setupChunkMocks(obj)
// // 				}
// // 			})
// // 			primaryFactory := primaryindex.NewFactory(func(obj *mock.Mock) {
// // 				if tt.setupPrimaryMocks != nil {
// // 					tt.setupPrimaryMocks(obj)
// // 				}
// // 			})
// // 			invertedFactory := invertedindex.NewFactory(func(obj *mock.Mock) {
// // 				if tt.setupInvertedMocks != nil {
// // 					tt.setupInvertedMocks(obj)
// // 				}
// // 			})
// // 			vectorFactory := vectorindex.NewFactory(func(obj *mock.Mock) {
// // 				if tt.setupVectorMocks != nil {
// // 					tt.setupVectorMocks(obj)
// // 				}
// // 			})

// // 			// Create block.
// // 			chunk, err := chunkFactory.New(&chunk.Config{
// // 				Path: "/tmp/append",
// // 			})
// // 			Expect(err).NotTo(HaveOccurred())
// // 			b := &block{
// // 				config:        atomic.Value{},
// // 				state:         atomic.Value{},
// // 				chunks:        chunkChain{chunk},
// // 				primaryIndex:  primaryFactory.New(),
// // 				invertedIndex: invertedFactory.New(),
// // 				vectorIndex:   vectorFactory.New(),
// // 				chunkFactory:  chunkFactory,
// // 			}
// // 			b.config.Store(&Config{
// // 				ParentDir: "/tmp",
// // 				Start:     t0,
// // 				Duration:  24 * time.Hour,
// // 			})
// // 			b.state.Store(tt.state)

// // 			// Execute test.
// // 			err = b.Append(context.Background(), tt.feeds...)
// // 			if tt.expectedErr != "" {
// // 				Expect(err).To(HaveOccurred())
// // 				Expect(err.Error()).To(ContainSubstring(tt.expectedErr))
// // 			} else {
// // 				Expect(err).NotTo(HaveOccurred())
// // 			}
// // 		})
// // 	}
// // }

// // func TestQuery(t *testing.T) {
// // 	RegisterTestingT(t)

// // 	t0 := time.Date(2025, 3, 3, 0, 0, 0, 0, time.UTC)
// // 	clk = clock.NewMock()
// // 	clk.(*clock.Mock).Set(t0)

// // 	tests := []struct {
// // 		scenario           string
// // 		given              string
// // 		when               string
// // 		then               string
// // 		state              State
// // 		setupChunkMocks    func(chunkMock *mock.Mock)
// // 		setupPrimaryMocks  func(primaryMock *mock.Mock)
// // 		setupInvertedMocks func(invertedMock *mock.Mock)
// // 		setupVectorMocks   func(vectorMock *mock.Mock)
// // 		queryOpts          QueryOptions
// // 		expectedFeeds      []*FeedVO
// // 		expectedErr        string
// // 	}{
// // 		{
// // 			scenario: "Query hot block with label filters",
// // 			given:    "a hot block with indexed feeds",
// // 			when:     "querying with label filters",
// // 			then:     "should return matching feeds",
// // 			state:    StateHot,
// // 			setupInvertedMocks: func(m *mock.Mock) {
// // 				m.On("Search", "k1", true, "v1").Return(map[uint64]bool{1: true})
// // 			},
// // 			setupPrimaryMocks: func(m *mock.Mock) {
// // 				m.On("Search", uint64(1)).Return(primaryindex.FeedRef{
// // 					Chunk:  0,
// // 					Offset: 0,
// // 					Time:   t0,
// // 				}, true)
// // 			},
// // 			setupChunkMocks: func(m *mock.Mock) {
// // 				m.On("Read", uint64(0)).Return(&chunk.Feed{
// // 					ID:     1,
// // 					Labels: model.Labels{model.Label{Key: "k1", Value: "v1"}},
// // 					Time:   t0,
// // 				}, nil)
// // 			},
// // 			queryOpts: QueryOptions{
// // 				Filters: []LabelFilter{{
// // 					Label: "k1",
// // 					Equal: true,
// // 					Value: "v1",
// // 				}},
// // 				Start: t0.Add(-1 * time.Hour),
// // 				End:   t0.Add(1 * time.Hour),
// // 			},
// // 			expectedFeeds: []*FeedVO{{
// // 				ID:     1,
// // 				Labels: model.Labels{model.Label{Key: "k1", Value: "v1"}},
// // 				Time:   t0,
// // 				Score:  0,
// // 			}},
// // 		},
// // 		{
// // 			scenario: "Query with semantic filter",
// // 			given:    "a block with vector indexed feeds",
// // 			when:     "querying with semantic filter",
// // 			then:     "should return semantically matching feeds with scores",
// // 			state:    StateHot,
// // 			setupVectorMocks: func(m *mock.Mock) {
// // 				m.On("Search", []float32{0.1, 0.2}, float32(0.8)).Return(map[uint64]float32{
// // 					1: 0.9,
// // 				})
// // 			},
// // 			setupPrimaryMocks: func(m *mock.Mock) {
// // 				m.On("Search", uint64(1)).Return(primaryindex.FeedRef{
// // 					Chunk:  0,
// // 					Offset: 0,
// // 					Time:   t0,
// // 				}, true)
// // 			},
// // 			setupChunkMocks: func(m *mock.Mock) {
// // 				m.On("Read", uint64(0)).Return(&chunk.Feed{
// // 					ID:      1,
// // 					Labels:  model.Labels{},
// // 					Time:    t0,
// // 					Vectors: [][]float32{{0.1, 0.2}},
// // 				}, nil)
// // 			},
// // 			queryOpts: QueryOptions{
// // 				SemanticFilter: SemanticFilter{
// // 					QueryVector: []float32{0.1, 0.2},
// // 					Threshold:   0.8,
// // 				},
// // 				Start: t0.Add(-1 * time.Hour),
// // 				End:   t0.Add(1 * time.Hour),
// // 			},
// // 			expectedFeeds: []*FeedVO{{
// // 				ID:     1,
// // 				Labels: model.Labels{},
// // 				Time:   t0,
// // 				Score:  0.9,
// // 			}},
// // 		},
// // 		{
// // 			scenario: "Query with time range filter",
// // 			given:    "a block with feeds at different times",
// // 			when:     "querying with time range",
// // 			then:     "should only return feeds within range",
// // 			state:    StateHot,
// // 			setupPrimaryMocks: func(m *mock.Mock) {
// // 				m.On("IDs").Return(map[uint64]bool{1: true, 2: true})
// // 				m.On("Search", uint64(1)).Return(primaryindex.FeedRef{
// // 					Chunk:  0,
// // 					Offset: 0,
// // 					Time:   t0,
// // 				}, true)
// // 				m.On("Search", uint64(2)).Return(primaryindex.FeedRef{
// // 					Chunk:  0,
// // 					Offset: 1,
// // 					Time:   t0.Add(2 * time.Hour),
// // 				}, true)
// // 			},
// // 			setupChunkMocks: func(m *mock.Mock) {
// // 				m.On("Read", uint64(0)).Return(&chunk.Feed{
// // 					ID:     1,
// // 					Labels: model.Labels{},
// // 					Time:   t0,
// // 				}, nil)
// // 			},
// // 			queryOpts: QueryOptions{
// // 				Start: t0.Add(-1 * time.Hour),
// // 				End:   t0.Add(1 * time.Hour),
// // 			},
// // 			expectedFeeds: []*FeedVO{{
// // 				ID:     1,
// // 				Labels: model.Labels{},
// // 				Time:   t0,
// // 			}},
// // 		},
// // 	}

// // 	for _, tt := range tests {
// // 		t.Run(tt.scenario, func(t *testing.T) {
// // 			// Create mock factories
// // 			chunkFactory := chunk.NewFactory(func(obj *mock.Mock) {
// // 				if tt.setupChunkMocks != nil {
// // 					tt.setupChunkMocks(obj)
// // 				}
// // 			})
// // 			primaryFactory := primaryindex.NewFactory(func(obj *mock.Mock) {
// // 				if tt.setupPrimaryMocks != nil {
// // 					tt.setupPrimaryMocks(obj)
// // 				}
// // 			})
// // 			invertedFactory := invertedindex.NewFactory(func(obj *mock.Mock) {
// // 				if tt.setupInvertedMocks != nil {
// // 					tt.setupInvertedMocks(obj)
// // 				}
// // 			})
// // 			vectorFactory := vectorindex.NewFactory(func(obj *mock.Mock) {
// // 				if tt.setupVectorMocks != nil {
// // 					tt.setupVectorMocks(obj)
// // 				}
// // 			})

// // 			// Create block
// // 			chunk, err := chunkFactory.New(&chunk.Config{
// // 				Path: "/tmp",
// // 			})
// // 			Expect(err).NotTo(HaveOccurred())

// // 			b := &block{
// // 				config:        atomic.Value{},
// // 				state:         atomic.Value{},
// // 				chunks:        chunkChain{chunk},
// // 				primaryIndex:  primaryFactory.New(),
// // 				invertedIndex: invertedFactory.New(),
// // 				vectorIndex:   vectorFactory.New(),
// // 				chunkFactory:  chunkFactory,
// // 				ctx:           context.Background(),
// // 				blockDirpath:  "/tmp",
// // 				chunkDirpath:  "/tmp/chunk",
// // 				indexDirpath:  "/tmp/index",
// // 			}
// // 			b.config.Store(&Config{
// // 				ParentDir: "/tmp",
// // 				Start:     t0,
// // 				Duration:  24 * time.Hour,
// // 			})
// // 			b.state.Store(tt.state)

// // 			// Execute test
// // 			feeds, err := b.Query(context.Background(), tt.queryOpts)

// // 			// Verify results
// // 			if tt.expectedErr != "" {
// // 				Expect(err).To(HaveOccurred())
// // 				Expect(err.Error()).To(ContainSubstring(tt.expectedErr))
// // 			} else {
// // 				Expect(err).NotTo(HaveOccurred())
// // 				Expect(feeds).To(HaveLen(len(tt.expectedFeeds)))
// // 				for i, feed := range feeds {
// // 					Expect(feed.ID).To(Equal(tt.expectedFeeds[i].ID))
// // 					Expect(feed.Labels).To(Equal(tt.expectedFeeds[i].Labels))
// // 					Expect(feed.Time).To(Equal(tt.expectedFeeds[i].Time))
// // 					Expect(feed.Score).To(Equal(tt.expectedFeeds[i].Score))
// // 				}
// // 			}
// // 		})
// // 	}
// // }
