package worker_test

import (
	"fmt"
	"testing"
	"time"

	"inboxer/src/internal/db"
	"inboxer/src/internal/imap"
	"inboxer/src/internal/worker"
	"inboxer/src/pkg/config"
)

// mockClassifier implements worker.AIClassifier for testing
type mockClassifier struct {
	folder     string
	confidence int
	err        error
}

func (m *mockClassifier) Classify(email imap.EmailSummary) (string, int, error) {
	return m.folder, m.confidence, m.err
}

// mockDB wraps the real database for testing (uses in-memory SQLite)
type mockDB struct {
	*db.Database
}

func newMockDB(t *testing.T) *db.Database {
	t.Helper()

	// We need a different approach since NewDatabase needs a file path
	// Use temporary file
	database, err := db.NewDatabase(t.TempDir()+"/test.db", "test-secret-key-32-bytes-long!!")
	if err != nil {
		t.Fatalf("failed to create test database: %v", err)
	}
	return database
}

func TestNewWorker(t *testing.T) {
	cfg := &config.Config{
		Worker: config.WorkerConfig{
			SteadyStateBatchSize:      10,
			SteadyStateIntervalMinutes: 5,
			CatchUpBatchSize:          50,
			CatchUpCooldownSeconds:    5,
		},
		Folders: config.FolderConfig{
			Important:     "Important",
			Ecommerce:     "eCommerce",
			Notifications: "Notifications",
			Finance:       "Finance",
			Social:        "Social",
			Other:         "Other",
			Spam:          "Spam",
		},
	}

	classifier := worker.NewPlaceholderClassifier("Other")
	w := worker.NewWorker(nil, cfg, classifier)

	if w == nil {
		t.Fatal("NewWorker returned nil")
	}
}

func TestNewPlaceholderClassifier(t *testing.T) {
	c := worker.NewPlaceholderClassifier("Other")
	if c == nil {
		t.Fatal("NewPlaceholderClassifier returned nil")
	}

	folder, confidence, err := c.Classify(imap.EmailSummary{
		UID:     1,
		Subject: "Test",
		From:    "test@example.com",
	})

	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if folder != "Other" {
		t.Errorf("expected folder 'Other', got %q", folder)
	}
	if confidence != 0 {
		t.Errorf("expected confidence 0, got %d", confidence)
	}
}

func TestPlaceholderClassifierFields(t *testing.T) {
	c := worker.NewPlaceholderClassifier("Work")
	if c.DefaultFolder != "Work" {
		t.Errorf("expected DefaultFolder 'Work', got %q", c.DefaultFolder)
	}

	folder, _, _ := c.Classify(imap.EmailSummary{UID: 42})
	if folder != "Work" {
		t.Errorf("expected folder 'Work', got %q", folder)
	}
}

func TestPlaceholderClassifierSubjectFrom(t *testing.T) {
	c := worker.NewPlaceholderClassifier("Spam")

	tests := []struct {
		name  string
		email imap.EmailSummary
	}{
		{"normal email", imap.EmailSummary{UID: 1, Subject: "Hello", From: "friend@example.com"}},
		{"empty subject", imap.EmailSummary{UID: 2, Subject: "", From: "noreply@example.com"}},
		{"empty from", imap.EmailSummary{UID: 3, Subject: "Test", From: ""}},
		{"all empty", imap.EmailSummary{UID: 4}},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			folder, _, err := c.Classify(tt.email)
			if err != nil {
				t.Fatalf("unexpected error: %v", err)
			}
			if folder != "Spam" {
				t.Errorf("expected 'Spam', got %q", folder)
			}
		})
	}
}

func TestStartStopWorker(t *testing.T) {
	database := newMockDB(t)
	cfg := &config.Config{
		Worker: config.WorkerConfig{
			SteadyStateBatchSize:      10,
			SteadyStateIntervalMinutes: 5,
			CatchUpBatchSize:          50,
			CatchUpCooldownSeconds:    1,
		},
		Folders: config.FolderConfig{
			Important:     "Important",
			Ecommerce:     "eCommerce",
			Notifications: "Notifications",
			Finance:       "Finance",
			Social:        "Social",
			Other:         "Other",
			Spam:          "Spam",
		},
	}

	classifier := worker.NewPlaceholderClassifier("Other")
	w := worker.NewWorker(database, cfg, classifier)

	// Start and immediately stop to test lifecycle
	w.Start()
	time.Sleep(100 * time.Millisecond) // Let it process
	w.Stop()

	// No assertion errors = pass
}

func TestProcessNowHandler(t *testing.T) {
	// Test that calling Start/Stop multiple times is safe
	database := newMockDB(t)
	cfg := &config.Config{
		Worker: config.WorkerConfig{
			SteadyStateBatchSize:      10,
			SteadyStateIntervalMinutes: 5,
			CatchUpBatchSize:          50,
			CatchUpCooldownSeconds:    1,
		},
		Folders: config.FolderConfig{
			Important:     "Important",
			Ecommerce:     "eCommerce",
			Notifications: "Notifications",
			Finance:       "Finance",
			Social:        "Social",
			Other:         "Other",
			Spam:          "Spam",
		},
	}

	classifier := worker.NewPlaceholderClassifier("Other")
	w := worker.NewWorker(database, cfg, classifier)

	// Start and stop multiple times (should be safe)
	w.Start()
	w.Start() // Second start should be safe
	time.Sleep(50 * time.Millisecond)
	w.Stop()
	w.Stop() // Second stop should be safe

	// Start one final time
	w.Start()
	time.Sleep(50 * time.Millisecond)
	w.Stop()
}

func TestMockClassifier(t *testing.T) {
	// Test with error
	errorClassifier := &mockClassifier{
		folder:     "",
		confidence: 0,
		err:        fmt.Errorf("classification failed"),
	}

	_, _, err := errorClassifier.Classify(imap.EmailSummary{UID: 1})
	if err == nil {
		t.Fatal("expected error from mock classifier")
	}

	// Test with specific folder
	successClassifier := &mockClassifier{
		folder:     "Important",
		confidence: 95,
		err:        nil,
	}

	folder, confidence, err := successClassifier.Classify(imap.EmailSummary{UID: 2})
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if folder != "Important" {
		t.Errorf("expected 'Important', got %q", folder)
	}
	if confidence != 95 {
		t.Errorf("expected 95, got %d", confidence)
	}
}
