package repository

import (
	"context"
	"fmt"

	libmongo "gateway/internal/library/mongo"
)

// MongoDB update-operator constants. Centralised so all permission Mongo
// repos use the same literal and goconst stays quiet.
const (
	bsonOpSet         = "$set"
	bsonOpSetOnInsert = "$setOnInsert"
	bsonOpIn          = "$in"
)

// EnsureMongoIndexes creates indexes for permission module collections.
// Safe to call repeatedly; index creation is idempotent in MongoDB.
func EnsureMongoIndexes(ctx context.Context, conf *libmongo.Conf) error {
	if conf == nil || conf.Host == "" {
		return nil
	}
	if err := ensurePermissionIndexes(ctx, conf); err != nil {
		return err
	}
	if err := ensureRoleIndexes(ctx, conf); err != nil {
		return err
	}
	if err := ensureRolePermissionIndexes(ctx, conf); err != nil {
		return err
	}
	if err := ensureUserRoleIndexes(ctx, conf); err != nil {
		return err
	}
	return ensureRoleMappingIndexes(ctx, conf)
}

func ensurePermissionIndexes(ctx context.Context, conf *libmongo.Conf) error {
	//nolint:contextcheck // repository ctor pings Mongo at startup without caller ctx
	repo, ok := NewPermissionRepository(PermissionRepositoryParam{Conf: conf}).(*permissionRepository)
	if !ok {
		return fmt.Errorf("permission: unexpected permission repository type")
	}
	return repo.Index20260521001UP(ctx)
}

func ensureRoleIndexes(ctx context.Context, conf *libmongo.Conf) error {
	//nolint:contextcheck // repository ctor pings Mongo at startup without caller ctx
	repo, ok := NewRoleRepository(RoleRepositoryParam{Conf: conf}).(*roleRepository)
	if !ok {
		return fmt.Errorf("permission: unexpected role repository type")
	}
	return repo.Index20260521001UP(ctx)
}

func ensureRolePermissionIndexes(ctx context.Context, conf *libmongo.Conf) error {
	//nolint:contextcheck // repository ctor pings Mongo at startup without caller ctx
	repo, ok := NewRolePermissionRepository(RolePermissionRepositoryParam{Conf: conf}).(*rolePermissionRepository)
	if !ok {
		return fmt.Errorf("permission: unexpected role_permission repository type")
	}
	return repo.Index20260521001UP(ctx)
}

func ensureUserRoleIndexes(ctx context.Context, conf *libmongo.Conf) error {
	//nolint:contextcheck // repository ctor pings Mongo at startup without caller ctx
	repo, ok := NewUserRoleRepository(UserRoleRepositoryParam{Conf: conf}).(*userRoleRepository)
	if !ok {
		return fmt.Errorf("permission: unexpected user_role repository type")
	}
	return repo.Index20260521001UP(ctx)
}

func ensureRoleMappingIndexes(ctx context.Context, conf *libmongo.Conf) error {
	//nolint:contextcheck // repository ctor pings Mongo at startup without caller ctx
	repo, ok := NewRoleMappingRepository(RoleMappingRepositoryParam{Conf: conf}).(*roleMappingRepository)
	if !ok {
		return fmt.Errorf("permission: unexpected role_mapping repository type")
	}
	return repo.Index20260521001UP(ctx)
}
