package search

import (
	"testing"
	"time"

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

func TestIndex(t *testing.T) {
	ws := NewWorkflowSearch()
	
	entry := &WorkflowEntry{
		ID:      "wf-1",
		Name:    "Deploy Service",
		Status:  "completed",
		Content: "deployment task",
	}
	
	err := ws.Index(entry)
	assert.NoError(t, err)
	
	retrieved, exists := ws.GetByID("wf-1")
	assert.True(t, exists)
	assert.Equal(t, "Deploy Service", retrieved.Name)
}

func TestSearch(t *testing.T) {
	ws := NewWorkflowSearch()
	
	ws.Index(&WorkflowEntry{
		ID:      "wf-1",
		Name:    "Deploy Service",
		Content: "deployment production",
	})
	ws.Index(&WorkflowEntry{
		ID:      "wf-2",
		Name:    "Build Docker",
		Content: "docker image",
	})
	
	results := ws.Search("deployment")
	assert.Equal(t, 1, len(results))
	assert.Equal(t, "wf-1", results[0].ID)
}

func TestFilterByStatus(t *testing.T) {
	ws := NewWorkflowSearch()
	
	ws.Index(&WorkflowEntry{ID: "wf-1", Status: "completed"})
	ws.Index(&WorkflowEntry{ID: "wf-2", Status: "running"})
	ws.Index(&WorkflowEntry{ID: "wf-3", Status: "completed"})
	
	results := ws.FilterByStatus("completed")
	assert.Equal(t, 2, len(results))
}

func TestFilterByAssignee(t *testing.T) {
	ws := NewWorkflowSearch()
	
	ws.Index(&WorkflowEntry{ID: "wf-1", Assignee: "alice"})
	ws.Index(&WorkflowEntry{ID: "wf-2", Assignee: "bob"})
	ws.Index(&WorkflowEntry{ID: "wf-3", Assignee: "alice"})
	
	results := ws.FilterByAssignee("alice")
	assert.Equal(t, 2, len(results))
}

func TestFilterByTag(t *testing.T) {
	ws := NewWorkflowSearch()
	
	ws.Index(&WorkflowEntry{
		ID:   "wf-1",
		Tags: []string{"production", "critical"},
	})
	ws.Index(&WorkflowEntry{
		ID:   "wf-2",
		Tags: []string{"staging"},
	})
	
	results := ws.FilterByTag("production")
	assert.Equal(t, 1, len(results))
}

func TestFilterByDateRange(t *testing.T) {
	ws := NewWorkflowSearch()
	
	now := time.Now()
	
	ws.Index(&WorkflowEntry{
		ID:        "wf-1",
		CreatedAt: now.Add(-1 * time.Hour),
	})
	ws.Index(&WorkflowEntry{
		ID:        "wf-2",
		CreatedAt: now.Add(-24 * time.Hour),
	})
	
	results := ws.FilterByDateRange(now.Add(-2*time.Hour), now)
	assert.Equal(t, 1, len(results))
}

func TestSearchRegex(t *testing.T) {
	ws := NewWorkflowSearch()
	
	ws.Index(&WorkflowEntry{
		ID:      "wf-1",
		Content: "error 404 not found",
	})
	ws.Index(&WorkflowEntry{
		ID:      "wf-2",
		Content: "success 200 ok",
	})
	
	results, err := ws.SearchRegex("error.*404")
	assert.NoError(t, err)
	assert.Equal(t, 1, len(results))
}

func TestSaveAndGetFilter(t *testing.T) {
	ws := NewWorkflowSearch()
	
	filter := map[string]interface{}{"status": "completed"}
	ws.SaveFilter("completed-only", filter)
	
	retrieved, exists := ws.GetFilter("completed-only")
	assert.True(t, exists)
	assert.NotNil(t, retrieved)
}

func TestGetAll(t *testing.T) {
	ws := NewWorkflowSearch()
	
	ws.Index(&WorkflowEntry{ID: "wf-1"})
	ws.Index(&WorkflowEntry{ID: "wf-2"})
	ws.Index(&WorkflowEntry{ID: "wf-3"})
	
	all := ws.GetAll()
	assert.Equal(t, 3, len(all))
}

func TestDelete(t *testing.T) {
	ws := NewWorkflowSearch()
	
	ws.Index(&WorkflowEntry{ID: "wf-1"})
	ws.Delete("wf-1")
	
	_, exists := ws.GetByID("wf-1")
	assert.False(t, exists)
}

func TestClear(t *testing.T) {
	ws := NewWorkflowSearch()
	
	ws.Index(&WorkflowEntry{ID: "wf-1"})
	ws.Index(&WorkflowEntry{ID: "wf-2"})
	ws.Clear()
	
	all := ws.GetAll()
	assert.Equal(t, 0, len(all))
}

func TestMultiwordSearch(t *testing.T) {
	ws := NewWorkflowSearch()
	
	ws.Index(&WorkflowEntry{
		ID:      "wf-1",
		Content: "deploy service to production",
	})
	
	results := ws.Search("deploy service")
	assert.Equal(t, 1, len(results))
}

func TestCaseSensitivity(t *testing.T) {
	ws := NewWorkflowSearch()
	
	ws.Index(&WorkflowEntry{
		ID:      "wf-1",
		Content: "Deploy Service Production",
	})
	
	results := ws.Search("deploy")
	assert.Equal(t, 1, len(results))
}

func TestIndexError(t *testing.T) {
	ws := NewWorkflowSearch()
	
	entry := &WorkflowEntry{
		Name: "No ID",
	}
	
	err := ws.Index(entry)
	assert.Error(t, err)
}
