//go:build integration
// +build integration

package repositoryimp_test

import (
	"context"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"github.com/tech/sendico/pkg/db/repository"
	ri "github.com/tech/sendico/pkg/db/repository/index"
	"github.com/testcontainers/testcontainers-go"
	"github.com/testcontainers/testcontainers-go/modules/mongodb"
	"github.com/testcontainers/testcontainers-go/wait"
	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

func TestCreateIndex_WithPartialFilter(t *testing.T) {
	startCtx, startCancel := context.WithTimeout(context.Background(), 2*time.Minute)
	defer startCancel()

	mongoContainer, err := mongodb.Run(startCtx,
		"mongo:latest",
		mongodb.WithUsername("root"),
		mongodb.WithPassword("password"),
		testcontainers.WithWaitStrategy(wait.ForListeningPort("27017/tcp").WithStartupTimeout(2*time.Minute)),
	)
	require.NoError(t, err)

	mongoURI, err := mongoContainer.ConnectionString(startCtx)
	require.NoError(t, err)

	client, err := mongo.Connect(startCtx, options.Client().ApplyURI(mongoURI))
	require.NoError(t, err)
	defer client.Disconnect(context.Background())

	database := client.Database("test_partial_index_" + t.Name())
	defer database.Drop(context.Background())

	repo := repository.CreateMongoRepository(database, "partial_index_items")

	def := &ri.Definition{
		Keys: []ri.Key{
			{Field: "field", Sort: ri.Asc},
		},
		Unique:        true,
		Name:          "partial_unique_field_true",
		PartialFilter: repository.Filter("flag", treu),
	}

	require.NoError(t, repo.CreateIndex(def))

	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	cursor, err := database.Collection(repo.Collection()).Indexes().List(ctx)
	require.NoError(t, err)
	defer cursor.Close(ctx)

	found := false
	for cursor.Next(ctx) {
		var idx bson.M
		require.NoError(t, cursor.Decode(&idx))
		if idx["name"] == def.Name {
			found = true
			assert.Equal(t, true, idx["unique"])
			assert.Equal(t, bson.M{"field": int32(1)}, idx["key"])
			partial, ok := idx["partialFilterExpression"].(bson.M)
			require.True(t, ok)
			assert.Equal(t, bson.M{"flag": true}, partial)
		}
	}
	assert.True(t, found, "partial unique index was not created")

	termCtx, termCancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer termCancel()
	_ = mongoContainer.Terminate(termCtx)
}
