package services

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestDashboardService_FilterHiddenCollections(t *testing.T) {
	service := &DashboardService{}

	sections := []DashboardSection{
		{CollectionName: "continue-reading", Title: "Continue Reading"},
		{CollectionName: "recently-added", Title: "Recently Added"},
		{CollectionName: "recently-read", Title: "Recently Read"},
		{CollectionName: "not-started", Title: "Not Started"},
	}

	tests := []struct {
		name             string
		hidden           []string
		expectedCount    int
		shouldContain    []string
		shouldNotContain []string
	}{
		{
			name:          "no hidden collections",
			hidden:        []string{},
			expectedCount: 4,
			shouldContain: []string{"continue-reading", "recently-added", "recently-read", "not-started"},
		},
		{
			name:             "one hidden collection",
			hidden:           []string{"not-started"},
			expectedCount:    3,
			shouldContain:    []string{"continue-reading", "recently-added", "recently-read"},
			shouldNotContain: []string{"not-started"},
		},
		{
			name:             "multiple hidden collections",
			hidden:           []string{"not-started", "recently-read"},
			expectedCount:    2,
			shouldContain:    []string{"continue-reading", "recently-added"},
			shouldNotContain: []string{"not-started", "recently-read"},
		},
		{
			name:          "hidden collection that doesn't exist",
			hidden:        []string{"non-existent"},
			expectedCount: 4,
			shouldContain: []string{"continue-reading", "recently-added", "recently-read", "not-started"},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := service.FilterHiddenCollections(sections, tt.hidden)

			assert.Equal(t, tt.expectedCount, len(result), "expected %d sections", tt.expectedCount)

			for _, name := range tt.shouldContain {
				found := false
				for _, section := range result {
					if section.CollectionName == name {
						found = true
						break
					}
				}
				assert.True(t, found, "expected section '%s' to be present", name)
			}

			for _, name := range tt.shouldNotContain {
				found := false
				for _, section := range result {
					if section.CollectionName == name {
						found = true
						break
					}
				}
				assert.False(t, found, "expected section '%s' to be filtered out", name)
			}
		})
	}
}

func TestDashboardService_ReorderCollections(t *testing.T) {
	service := &DashboardService{}

	sections := []DashboardSection{
		{CollectionName: "continue-reading", Title: "Continue Reading", Priority: 1},
		{CollectionName: "recently-added", Title: "Recently Added", Priority: 2},
		{CollectionName: "recently-read", Title: "Recently Read", Priority: 3},
		{CollectionName: "not-started", Title: "Not Started", Priority: 4},
	}

	tests := []struct {
		name           string
		customOrder    []string
		expectedFirst  string
		expectedSecond string
		expectedLast   string
	}{
		{
			name:           "no custom order (should keep original order)",
			customOrder:    []string{},
			expectedFirst:  "continue-reading",
			expectedSecond: "recently-added",
			expectedLast:   "not-started",
		},
		{
			name:           "custom order specified",
			customOrder:    []string{"not-started", "recently-added", "continue-reading", "recently-read"},
			expectedFirst:  "not-started",
			expectedSecond: "recently-added",
			expectedLast:   "recently-read",
		},
		{
			name:           "partial custom order (missing items go to end)",
			customOrder:    []string{"not-started", "continue-reading"},
			expectedFirst:  "not-started",
			expectedSecond: "continue-reading",
			expectedLast:   "recently-read",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := service.reorderCollections(sections, tt.customOrder)

			if len(result) > 0 {
				assert.Equal(t, tt.expectedFirst, result[0].CollectionName, "first section mismatch")
			}
			if len(result) > 1 {
				assert.Equal(t, tt.expectedSecond, result[1].CollectionName, "second section mismatch")
			}
			if len(result) > 0 {
				assert.Equal(t, tt.expectedLast, result[len(result)-1].CollectionName, "last section mismatch")
			}
		})
	}
}

func TestDashboardService_SortByPriority(t *testing.T) {
	service := &DashboardService{}

	sections := []DashboardSection{
		{CollectionName: "recently-read", Title: "Recently Read", Priority: 3},
		{CollectionName: "continue-reading", Title: "Continue Reading", Priority: 1},
		{CollectionName: "not-started", Title: "Not Started", Priority: 4},
		{CollectionName: "recently-added", Title: "Recently Added", Priority: 2},
	}

	result := service.sortByPriority(sections)

	require.Equal(t, 4, len(result), "expected 4 sections")

	assert.Equal(t, "continue-reading", result[0].CollectionName, "first should be priority 1")
	assert.Equal(t, 1, result[0].Priority, "first section priority")

	assert.Equal(t, "recently-added", result[1].CollectionName, "second should be priority 2")
	assert.Equal(t, 2, result[1].Priority, "second section priority")

	assert.Equal(t, "recently-read", result[2].CollectionName, "third should be priority 3")
	assert.Equal(t, 3, result[2].Priority, "third section priority")

	assert.Equal(t, "not-started", result[3].CollectionName, "fourth should be priority 4")
	assert.Equal(t, 4, result[3].Priority, "fourth section priority")
}

func TestDashboardService_SortByPriority_Empty(t *testing.T) {
	service := &DashboardService{}

	sections := []DashboardSection{}
	result := service.sortByPriority(sections)

	assert.Equal(t, 0, len(result), "expected empty result")
}

func TestDashboardService_SortByPriority_Single(t *testing.T) {
	service := &DashboardService{}

	sections := []DashboardSection{
		{CollectionName: "continue-reading", Title: "Continue Reading", Priority: 1},
	}

	result := service.sortByPriority(sections)

	assert.Equal(t, 1, len(result), "expected 1 section")
	assert.Equal(t, "continue-reading", result[0].CollectionName)
}
