// 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/>.

package scrape

// import (
// 	"testing"
// 	"time"

// 	. "github.com/onsi/gomega"
// )

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

// 	tests := []struct {
// 		scenario string
// 		given    string
// 		when     string
// 		then     string
// 		config   *Config
// 		want     *Config
// 		wantErr  string
// 	}{
// 		{
// 			scenario: "Valid Configuration",
// 			given:    "a valid configuration with RSS sources",
// 			when:     "creating a new manager",
// 			then:     "should create manager successfully",
// 			config: &Config{
// 				ScrapeInterval: time.Second,
// 				RSSs: []RSS{
// 					{
// 						Name:           "test",
// 						URL:            "http://example.com",
// 						ScrapeInterval: time.Second,
// 						Labels:         map[string]string{},
// 					},
// 				},
// 			},
// 		},
// 		{
// 			scenario: "Invalid Global Interval",
// 			given:    "a configuration with invalid global scrape interval",
// 			when:     "creating a new manager",
// 			then:     "should return interval validation error",
// 			config: &Config{
// 				ScrapeInterval: time.Millisecond,
// 			},
// 			wantErr: "scrape interval must be at least 1 second",
// 		},
// 		{
// 			scenario: "Invalid RSS Config",
// 			given:    "a configuration with invalid RSS config",
// 			when:     "creating a new manager",
// 			then:     "should return RSS config validation error",
// 			config: &Config{
// 				ScrapeInterval: time.Second,
// 				RSSs: []RSS{
// 					{
// 						Name:           "",
// 						URL:            "",
// 						ScrapeInterval: time.Second,
// 						Labels:         map[string]string{},
// 					},
// 				},
// 			},
// 			wantErr: "invalid RSS config",
// 		},
// 		{
// 			scenario: "Default Global Interval",
// 			given:    "a configuration with zero global interval",
// 			when:     "validating and adjusting the config",
// 			then:     "should set default global interval",
// 			config: &Config{
// 				ScrapeInterval: 0,
// 				RSSs: []RSS{
// 					{
// 						Name:           "test",
// 						URL:            "http://example.com",
// 						ScrapeInterval: time.Second,
// 						Labels:         map[string]string{},
// 					},
// 				},
// 			},
// 			want: &Config{
// 				ScrapeInterval: time.Hour, // default value
// 				RSSs: []RSS{
// 					{
// 						Name:           "test",
// 						URL:            "http://example.com",
// 						ScrapeInterval: time.Hour, // inherited from global
// 						Labels:         map[string]string{},
// 					},
// 				},
// 			},
// 		},
// 		{
// 			scenario: "Default RSS Interval",
// 			given:    "a configuration with zero RSS interval",
// 			when:     "validating and adjusting the config",
// 			then:     "should inherit global interval",
// 			config: &Config{
// 				ScrapeInterval: time.Minute,
// 				RSSs: []RSS{
// 					{
// 						Name:   "test",
// 						URL:    "http://example.com",
// 						Labels: map[string]string{},
// 					},
// 				},
// 			},
// 			want: &Config{
// 				ScrapeInterval: time.Minute,
// 				RSSs: []RSS{
// 					{
// 						Name:           "test",
// 						URL:            "http://example.com",
// 						ScrapeInterval: time.Minute,
// 						Labels:         map[string]string{},
// 					},
// 				},
// 			},
// 		},
// 	}

// 	for _, tt := range tests {
// 		t.Run(tt.scenario, func(t *testing.T) {
// 			err := tt.config.Validate()
// 			if tt.wantErr != "" {
// 				Expect(err).To(HaveOccurred())
// 				Expect(err.Error()).To(ContainSubstring(tt.wantErr))
// 			} else {
// 				Expect(err).NotTo(HaveOccurred())
// 				if tt.want != nil {
// 					Expect(tt.config).To(Equal(tt.want))
// 				}
// 			}
// 		})
// 	}
// }

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

// // 	tests := []struct {
// // 		scenario  string
// // 		given     string
// // 		when      string
// // 		then      string
// // 		config    *Config
// // 		mockSetup func(*mockScraperFactory)
// // 		wantErr   string
// // 	}{
// // 		{
// // 			scenario: "Basic Run",
// // 			given:    "a valid configuration with one RSS source",
// // 			when:     "running the manager",
// // 			then:     "should start scraper successfully",
// // 			config: &Config{
// // 				ScrapeInterval: time.Second,
// // 				RSSs: []RSS{
// // 					{
// // 						Config: &rss.Config{
// // 							WebsiteName: "Test",
// // 							Name:        "test",
// // 							URL:         "http://example.com",
// // 						},
// // 					},
// // 				},
// // 			},
// // 			mockSetup: func(f *mockScraperFactory) {
// // 				mockScraper := scraper.NewMock()
// // 				mockScraper.On("Config").Return(&scraper.Config{})
// // 				mockScraper.On("Run").Return()
// // 				mockScraper.On("Stop").Return()
// // 				f.On("New", mock.Anything, mock.Anything).Return(mockScraper, nil)
// // 			},
// // 		},
// // 		{
// // 			scenario: "Scraper Creation Failure",
// // 			given:    "a configuration that causes scraper creation to fail",
// // 			when:     "running the manager",
// // 			then:     "should return error",
// // 			config: &Config{
// // 				ScrapeInterval: time.Second,
// // 				RSSs: []RSS{
// // 					{
// // 						Config: &rss.Config{
// // 							WebsiteName: "Test",
// // 							Name:        "test",
// // 							URL:         "http://example.com",
// // 						},
// // 					},
// // 				},
// // 			},
// // 			mockSetup: func(f *mockScraperFactory) {
// // 				f.On("New", mock.Anything, mock.Anything).Return(nil, errors.New("scraper creation failed"))
// // 			},
// // 			wantErr: "creating RSS scraper",
// // 		},
// // 	}

// // 	for _, tt := range tests {
// // 		t.Run(tt.scenario, func(t *testing.T) {
// // 			mockReader := feedreader.NewMock()
// // 			mockWriter := feedwriter.NewMock()
// // 			mockDB := db.New(mockWriter, mockReader)
// // 			m, err := NewManager(tt.config, mockDB)
// // 			Expect(err).NotTo(HaveOccurred())

// // 			mockFactory := newMockScraperFactory()
// // 			defer mockFactory.AssertExpectations(t)
// // 			if tt.mockSetup != nil {
// // 				tt.mockSetup(mockFactory)
// // 			}
// // 			mgr := m.(*manager)
// // 			mgr.rssScraperFactory = mockFactory

// // 			ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
// // 			defer cancel()

// // 			err = m.Run(ctx)
// // 			if tt.wantErr != "" {
// // 				Expect(err).To(HaveOccurred())
// // 				Expect(err.Error()).To(ContainSubstring(tt.wantErr))
// // 			} else {
// // 				Expect(err).NotTo(HaveOccurred())
// // 			}
// // 		})
// // 	}
// // }

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

// // 	tests := []struct {
// // 		scenario   string
// // 		given      string
// // 		when       string
// // 		then       string
// // 		initConfig *Config
// // 		newConfig  *Config
// // 		mockSetup  func(*mockScraperFactory)
// // 		validate   func(Manager)
// // 		wantErr    string
// // 	}{
// // 		{
// // 			scenario: "Valid Config Update",
// // 			given:    "a running manager and valid new configuration",
// // 			when:     "reloading with new config",
// // 			then:     "should update scrapers successfully",
// // 			initConfig: &Config{
// // 				ScrapeInterval: time.Second,
// // 				RSSs: []RSS{
// // 					{
// // 						Config: &rss.Config{
// // 							WebsiteName: "Test",
// // 							Name:        "test1",
// // 							URL:         "http://example1.com",
// // 						},
// // 					},
// // 				},
// // 			},
// // 			newConfig: &Config{
// // 				ScrapeInterval: time.Second,
// // 				RSSs: []RSS{
// // 					{
// // 						Config: &rss.Config{
// // 							WebsiteName: "Test",
// // 							Name:        "test1",
// // 							URL:         "http://example1.com",
// // 						},
// // 					},
// // 					{
// // 						Config: &rss.Config{
// // 							WebsiteName: "Test",
// // 							Name:        "test2",
// // 							URL:         "http://example2.com",
// // 						},
// // 					},
// // 				},
// // 			},
// // 			mockSetup: func(f *mockScraperFactory) {
// // 				mockScraper1 := scraper.NewMock()
// // 				mockScraper1.On("Config").Return(&scraper.Config{
// // 					Interval:        time.Second,
// // 					RetentionPeriod: 24 * time.Hour,
// // 				})
// // 				mockScraper1.On("Run").Return()
// // 				mockScraper1.On("Stop").Return()

// // 				mockScraper2 := scraper.NewMock()
// // 				mockScraper2.On("Config").Return(&scraper.Config{
// // 					Interval:        time.Second,
// // 					RetentionPeriod: 24 * time.Hour,
// // 				})
// // 				mockScraper2.On("Run").Return()
// // 				mockScraper2.On("Stop").Return()

// // 				f.On("New", mock.Anything, mock.Anything).Return(mockScraper1, nil).Once()
// // 				f.On("New", mock.Anything, mock.Anything).Return(mockScraper2, nil).Once()
// // 			},
// // 			validate: func(m Manager) {
// // 				mgr := m.(*manager)
// // 				Expect(mgr.scrapers).To(HaveLen(2))
// // 				for id := range mgr.scrapers {
// // 					Expect(id).To(BeElementOf([]string{"rss/Test/test1", "rss/Test/test2"}))
// // 				}
// // 			},
// // 		},
// // 		{
// // 			scenario: "Invalid New Config",
// // 			given:    "a running manager and invalid new configuration",
// // 			when:     "reloading with invalid config",
// // 			then:     "should return validation error",
// // 			initConfig: &Config{
// // 				ScrapeInterval: time.Second,
// // 				RSSs: []RSS{
// // 					{
// // 						Config: &rss.Config{
// // 							WebsiteName: "Test",
// // 							Name:        "test",
// // 							URL:         "http://example.com",
// // 						},
// // 					},
// // 				},
// // 			},
// // 			newConfig: &Config{
// // 				ScrapeInterval: time.Millisecond,
// // 			},
// // 			mockSetup: func(f *mockScraperFactory) {
// // 				mockScraper := scraper.NewMock()
// // 				mockScraper.On("Config").Return(&scraper.Config{})
// // 				mockScraper.On("Run").Return()
// // 				mockScraper.On("Stop").Return()
// // 				f.On("New", mock.Anything, mock.Anything).Return(mockScraper, nil).Maybe()
// // 			},
// // 			wantErr: "scrape interval must be at least 1 second",
// // 		},
// // 		{
// // 			scenario: "Keep Unchanged Scraper",
// // 			given:    "a running scraper with unchanged config",
// // 			when:     "reloading with same config",
// // 			then:     "should keep the same scraper instance",
// // 			initConfig: &Config{
// // 				ScrapeInterval: time.Second,
// // 				RSSs: []RSS{
// // 					{
// // 						Config: &rss.Config{
// // 							WebsiteName: "Test",
// // 							Name:        "test",
// // 							URL:         "http://example.com",
// // 						},
// // 					},
// // 				},
// // 			},
// // 			newConfig: &Config{
// // 				ScrapeInterval: time.Second,
// // 				RSSs: []RSS{
// // 					{
// // 						Config: &rss.Config{
// // 							WebsiteName: "Test",
// // 							Name:        "test",
// // 							URL:         "http://example.com",
// // 						},
// // 					},
// // 				},
// // 			},
// // 			mockSetup: func(f *mockScraperFactory) {
// // 				mockScraper := scraper.NewMock()
// // 				mockScraper.On("Config").Return(&scraper.Config{
// // 					Interval:        time.Second,
// // 					RetentionPeriod: 24 * time.Hour,
// // 				})
// // 				mockScraper.On("Run").Return()
// // 				mockScraper.On("Stop").Return()
// // 				f.On("New", mock.Anything, mock.Anything).Return(mockScraper, nil).Once()
// // 			},
// // 			validate: func(m Manager) {
// // 				mgr := m.(*manager)
// // 				Expect(mgr.scrapers).To(HaveLen(1))
// // 				Expect(mgr.scrapers["rss/Test/test"].Config().Interval).To(Equal(time.Second))
// // 			},
// // 		},
// // 		{
// // 			scenario: "Stop Removed Scraper",
// // 			given:    "a running scraper",
// // 			when:     "reloading with empty config",
// // 			then:     "should stop and remove the scraper",
// // 			initConfig: &Config{
// // 				ScrapeInterval: time.Second,
// // 				RSSs: []RSS{
// // 					{
// // 						Config: &rss.Config{
// // 							WebsiteName: "Test",
// // 							Name:        "test",
// // 							URL:         "http://example.com",
// // 						},
// // 					},
// // 				},
// // 			},
// // 			newConfig: &Config{
// // 				ScrapeInterval: time.Second,
// // 				RSSs:           []RSS{},
// // 			},
// // 			mockSetup: func(f *mockScraperFactory) {
// // 				mockScraper := scraper.NewMock()
// // 				mockScraper.On("Config").Return(&scraper.Config{
// // 					Interval:        time.Second,
// // 					RetentionPeriod: 24 * time.Hour,
// // 				})
// // 				mockScraper.On("Run").Return()
// // 				mockScraper.On("Stop").Return().Once()
// // 				f.On("New", mock.Anything, mock.Anything).Return(mockScraper, nil).Once()
// // 			},
// // 			validate: func(m Manager) {
// // 				mgr := m.(*manager)
// // 				Expect(mgr.scrapers).To(BeEmpty())
// // 			},
// // 		},
// // 		{
// // 			scenario: "Restart Changed Scraper",
// // 			given:    "a running scraper",
// // 			when:     "reloading with modified config",
// // 			then:     "should stop old scraper and start new one",
// // 			initConfig: &Config{
// // 				ScrapeInterval: time.Second,
// // 				RSSs: []RSS{
// // 					{
// // 						Config: &rss.Config{
// // 							WebsiteName: "Test",
// // 							Name:        "test",
// // 							URL:         "http://example.com",
// // 						},
// // 						Scrape: &scraper.Config{
// // 							Interval: time.Second,
// // 						},
// // 					},
// // 				},
// // 			},
// // 			newConfig: &Config{
// // 				ScrapeInterval: time.Second,
// // 				RSSs: []RSS{
// // 					{
// // 						Config: &rss.Config{
// // 							WebsiteName: "Test",
// // 							Name:        "test",
// // 							URL:         "http://example.com",
// // 						},
// // 						Scrape: &scraper.Config{
// // 							Interval: time.Minute,
// // 						},
// // 					},
// // 				},
// // 			},
// // 			mockSetup: func(f *mockScraperFactory) {
// // 				mockScraper1 := scraper.NewMock()
// // 				mockScraper1.On("Config").Return(&scraper.Config{
// // 					Interval:        time.Second,
// // 					RetentionPeriod: 24 * time.Hour,
// // 				})
// // 				mockScraper1.On("Run").Return()
// // 				mockScraper1.On("Stop").Return().Once()

// // 				mockScraper2 := scraper.NewMock()
// // 				mockScraper2.On("Config").Return(&scraper.Config{
// // 					Interval: time.Minute,
// // 				})
// // 				mockScraper2.On("Run").Return()
// // 				mockScraper2.On("Stop").Return()

// // 				f.On("New", mock.Anything, mock.Anything).Return(mockScraper1, nil).Once()
// // 				f.On("New", mock.Anything, mock.Anything).Return(mockScraper2, nil).Once()
// // 			},
// // 			validate: func(m Manager) {
// // 				mgr := m.(*manager)
// // 				Expect(mgr.scrapers).To(HaveLen(1))
// // 				Expect(mgr.scrapers["rss/Test/test"].Config().Interval).To(Equal(time.Minute))
// // 			},
// // 		},
// // 	}

// // 	for _, tt := range tests {
// // 		t.Run(tt.scenario, func(t *testing.T) {
// // 			mockReader := feedreader.NewMock()
// // 			mockWriter := feedwriter.NewMock()
// // 			mockDB := db.New(mockWriter, mockReader)
// // 			m, err := NewManager(tt.initConfig, mockDB)
// // 			Expect(err).NotTo(HaveOccurred())

// // 			mgr := m.(*manager)
// // 			mockFactory := newMockScraperFactory()
// // 			defer mockFactory.AssertExpectations(t)
// // 			if tt.mockSetup != nil {
// // 				tt.mockSetup(mockFactory)
// // 			}
// // 			mgr.rssScraperFactory = mockFactory

// // 			ctx, cancel := context.WithCancel(context.Background())
// // 			defer cancel()
// // 			go func() {
// // 				_ = m.Run(ctx)
// // 			}()
// // 			time.Sleep(50 * time.Millisecond)

// // 			err = m.Reload(tt.newConfig)
// // 			if tt.wantErr != "" {
// // 				Expect(err).To(HaveOccurred())
// // 				Expect(err.Error()).To(ContainSubstring(tt.wantErr))
// // 			} else {
// // 				Expect(err).NotTo(HaveOccurred())
// // 			}
// // 			if tt.validate != nil {
// // 				tt.validate(m)
// // 			}
// // 		})
// // 	}
// // }

// // 			mgr := m.(*manager)
// // 			mockFactory := newMockScraperFactory()
// // 			defer mockFactory.AssertExpectations(t)
// // 			if tt.mockSetup != nil {
// // 				tt.mockSetup(mockFactory)
// // 			}
// // 			mgr.rssScraperFactory = mockFactory

// // 			ctx, cancel := context.WithCancel(context.Background())
// // 			defer cancel()
// // 			go func() {
// // 				_ = m.Run(ctx)
// // 			}()
// // 			time.Sleep(50 * time.Millisecond)

// // 			err = m.Reload(tt.newConfig)
// // 			if tt.wantErr != "" {
// // 				Expect(err).To(HaveOccurred())
// // 				Expect(err.Error()).To(ContainSubstring(tt.wantErr))
// // 			} else {
// // 				Expect(err).NotTo(HaveOccurred())
// // 			}
// // 			if tt.validate != nil {
// // 				tt.validate(m)
// // 			}
// // 		})
// // 	}
// // }
