package store

import (
	"context"
	"fmt"

	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

// EnsureIndexes creates every index from spec §4.9. CreateMany is idempotent:
// existing identical indexes are no-ops, so this runs safely at every startup.
func EnsureIndexes(ctx context.Context, db *mongo.Database) error {
	plan := map[string][]mongo.IndexModel{
		"users": {
			{Keys: bson.D{{Key: "email", Value: 1}}, Options: options.Index().SetUnique(true)},
			{Keys: bson.D{{Key: "auth.oidc.issuer", Value: 1}, {Key: "auth.oidc.subject", Value: 1}},
				Options: options.Index().SetUnique(true).SetSparse(true)},
		},
		"customers": {
			{Keys: bson.D{{Key: "name", Value: 1}}, Options: options.Index().SetUnique(true)},
			{Keys: bson.D{{Key: "consultantIds", Value: 1}}},
		},
		"pools": {
			{Keys: bson.D{{Key: "consultantId", Value: 1}, {Key: "developerId", Value: 1}},
				Options: options.Index().SetUnique(true)},
			{Keys: bson.D{{Key: "developerId", Value: 1}}},
		},
		"tasks": {
			{Keys: bson.D{{Key: "customerId", Value: 1}, {Key: "status", Value: 1}, {Key: "updatedAt", Value: -1}}},
			{Keys: bson.D{{Key: "consultantId", Value: 1}, {Key: "status", Value: 1}, {Key: "updatedAt", Value: -1}}},
			{Keys: bson.D{{Key: "assignee.userId", Value: 1}, {Key: "status", Value: 1}}},
			{Keys: bson.D{{Key: "rootId", Value: 1}}},
			{Keys: bson.D{{Key: "parentId", Value: 1}}},
			// The spec calls this "unique sparse", but a compound sparse index
			// matches any doc where customerId exists (i.e. every task), which
			// breaks subdivided children. A partial index expresses the intent:
			// uniqueness only for tasks that actually have an external ref.
			{Keys: bson.D{{Key: "external.system", Value: 1}, {Key: "external.key", Value: 1}, {Key: "customerId", Value: 1}},
				Options: options.Index().SetUnique(true).SetName("uniq_external_ref").
					SetPartialFilterExpression(bson.M{"external.key": bson.M{"$exists": true}})},
			{Keys: bson.D{{Key: "title", Value: "text"}, {Key: "description", Value: "text"}}},
		},
		"bountyAwards": {
			{Keys: bson.D{{Key: "developerId", Value: 1}, {Key: "awardedAt", Value: -1}}},
			{Keys: bson.D{{Key: "consultantId", Value: 1}, {Key: "awardedAt", Value: -1}}},
			{Keys: bson.D{{Key: "customerId", Value: 1}, {Key: "awardedAt", Value: -1}}},
		},
		"conversations": {
			{Keys: bson.D{{Key: "participantIds", Value: 1}, {Key: "lastMessageAt", Value: -1}}},
			{Keys: bson.D{{Key: "kind", Value: 1}, {Key: "customerId", Value: 1}}},
		},
		"notifications": {
			{Keys: bson.D{{Key: "userId", Value: 1}, {Key: "readAt", Value: 1}, {Key: "createdAt", Value: -1}}},
		},
		"sessions": {
			{Keys: bson.D{{Key: "expiresAt", Value: 1}}, Options: options.Index().SetExpireAfterSeconds(0)},
			{Keys: bson.D{{Key: "userId", Value: 1}}},
		},
		"passwordResets": {
			{Keys: bson.D{{Key: "expiresAt", Value: 1}}, Options: options.Index().SetExpireAfterSeconds(0)},
		},
		"messages": {
			// ULID _id is time-ordered, so this serves history pagination.
			{Keys: bson.D{{Key: "conversationId", Value: 1}, {Key: "_id", Value: 1}}},
			{Keys: bson.D{{Key: "attachments.fileId", Value: 1}}, Options: options.Index().SetSparse(true)},
		},
		"auditLog": {
			{Keys: bson.D{{Key: "at", Value: -1}}},
			{Keys: bson.D{{Key: "entityId", Value: 1}, {Key: "at", Value: -1}}},
		},
	}

	// migration: an earlier build created the external-ref index as sparse
	// under the auto-generated name; drop it so the partial variant applies
	_ = db.Collection("tasks").Indexes().DropOne(ctx, "external.system_1_external.key_1_customerId_1")

	for coll, models := range plan {
		if _, err := db.Collection(coll).Indexes().CreateMany(ctx, models); err != nil {
			return fmt.Errorf("create indexes for %s: %w", coll, err)
		}
	}
	return nil
}
