package mongo

import (
	"context"
	"testing"
	"time"
)

func TestNewDocumentDB(t *testing.T) {
	// Test with valid config
	conf := &Conf{
		Host:     "localhost:27017",
		Database: "testdb",
	}

	db, err := NewDocumentDB(conf, "testcollection")

	// Note: This will fail in test environment without MongoDB running
	// but we can test the error handling and basic structure
	if err == nil {
		t.Log("MongoDB connection successful (MongoDB is running)")

		// Test basic properties
		if db == nil {
			t.Error("Expected DocumentDB to be non-nil")
		}

		// Test GetClient
		client := db.GetClient()
		if client == nil {
			t.Error("Expected client to be non-nil")
		}

		// Test that we got a valid DocumentDB
		if db == nil {
			t.Error("Expected DocumentDB to be non-nil")
		}
	} else {
		t.Logf("MongoDB connection failed (expected in test environment): %v", err)
	}
}

func TestDocumentDB_PopulateIndex(t *testing.T) {
	// Test with mock data
	conf := &Conf{
		Host:     "localhost:27017",
		Database: "testdb",
	}

	db, err := NewDocumentDB(conf, "testcollection")

	if err != nil {
		t.Skip("Skipping test - MongoDB not available")
		return
	}

	// Test index creation
	ctx := context.Background()
	db.PopulateIndex(ctx, "field1", 1, false)
}

func TestDocumentDB_PopulateTTLIndex(t *testing.T) {
	conf := &Conf{
		Host:     "localhost:27017",
		Database: "testdb",
	}

	db, err := NewDocumentDB(conf, "testcollection")

	if err != nil {
		t.Skip("Skipping test - MongoDB not available")
		return
	}

	// Test TTL index creation
	ctx := context.Background()
	ttl := int32(3600) // 1 hour
	db.PopulateTTLIndex(ctx, "expireAt", 1, false, ttl)
}

func TestDocumentDB_PopulateMultiIndex(t *testing.T) {
	conf := &Conf{
		Host:     "localhost:27017",
		Database: "testdb",
	}

	db, err := NewDocumentDB(conf, "testcollection")

	if err != nil {
		t.Skip("Skipping test - MongoDB not available")
		return
	}

	// Test multiple index creation
	ctx := context.Background()
	keys := []string{"field1", "field2", "field3"}
	sorts := []int32{1, -1, 1}
	db.PopulateMultiIndex(ctx, keys, sorts, false)
}

func TestDocumentDB_GetClient(t *testing.T) {
	conf := &Conf{
		Host:     "localhost:27017",
		Database: "testdb",
	}

	db, err := NewDocumentDB(conf, "testcollection")

	if err != nil {
		t.Skip("Skipping test - MongoDB not available")
		return
	}

	client := db.GetClient()
	if client == nil {
		t.Error("Expected client to be non-nil")
	}
}

func TestDocumentDB_DatabaseName(t *testing.T) {
	conf := &Conf{
		Host:     "localhost:27017",
		Database: "testdb",
	}

	db, err := NewDocumentDB(conf, "testcollection")

	if err != nil {
		t.Skip("Skipping test - MongoDB not available")
		return
	}

	// Test that we got a valid DocumentDB
	if db == nil {
		t.Error("Expected DocumentDB to be non-nil")
	}
}

func TestDocumentDB_WithDifferentConfigs(t *testing.T) {
	testCases := []struct {
		name string
		conf *Conf
	}{
		{
			name: "minimal config",
			conf: &Conf{
				Host: "localhost:27017",
			},
		},
		{
			name: "with database",
			conf: &Conf{
				Host:     "localhost:27017",
				Database: "testdb",
			},
		},
		{
			name: "with credentials",
			conf: &Conf{
				Host:     "localhost:27017",
				Database: "testdb",
				User:     "user",
				Password: "pass",
			},
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			db, err := NewDocumentDB(tc.conf, "testcollection")

			if err != nil {
				t.Logf("MongoDB connection failed (expected in test environment): %v", err)
				return
			}

			if db == nil {
				t.Error("Expected DocumentDB to be non-nil")
			}
		})
	}
}

func TestDocumentDB_IndexOperations(t *testing.T) {
	conf := &Conf{
		Host:     "localhost:27017",
		Database: "testdb",
	}

	db, err := NewDocumentDB(conf, "testcollection")

	if err != nil {
		t.Skip("Skipping test - MongoDB not available")
		return
	}

	// Test single index
	ctx := context.Background()
	db.PopulateIndex(ctx, "single_field", 1, false)

	// Test TTL index
	ttl := int32(1800) // 30 minutes
	db.PopulateTTLIndex(ctx, "expiresAt", 1, false, ttl)

	// Test multiple indexes
	keys := []string{"field1", "field2", "compound_field1"}
	sorts := []int32{1, -1, 1}
	db.PopulateMultiIndex(ctx, keys, sorts, false)
}

func TestDocumentDB_ContextHandling(t *testing.T) {
	conf := &Conf{
		Host:     "localhost:27017",
		Database: "testdb",
	}

	// Test with timeout context
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	db, err := NewDocumentDB(conf, "testcollection")

	// Use ctx to avoid unused variable warning
	_ = ctx

	if err != nil {
		t.Logf("MongoDB connection failed (expected in test environment): %v", err)
		return
	}

	if db == nil {
		t.Error("Expected DocumentDB to be non-nil")
	}
}

func TestDocumentDB_ErrorHandling(t *testing.T) {
	// Test with invalid config
	invalidConf := &Conf{
		Host: "invalid-host:99999",
	}

	_, err := NewDocumentDB(invalidConf, "testcollection")

	// This should fail
	if err == nil {
		t.Error("Expected error with invalid host, got nil")
	}
}

func TestDocumentDB_IndexModelCreation(t *testing.T) {
	// Test the yieldIndexModel function indirectly through PopulateIndex
	conf := &Conf{
		Host:     "localhost:27017",
		Database: "testdb",
	}

	db, err := NewDocumentDB(conf, "testcollection")

	if err != nil {
		t.Skip("Skipping test - MongoDB not available")
		return
	}

	// Test with various index configurations
	ctx := context.Background()
	db.PopulateIndex(ctx, "ascending", 1, false)
	db.PopulateIndex(ctx, "descending", -1, false)
}
