package callbacksdb

import (
	"context"

	"github.com/tech/sendico/pkg/auth"
	"github.com/tech/sendico/pkg/db/callbacks"
	"github.com/tech/sendico/pkg/db/policy"
	ri "github.com/tech/sendico/pkg/db/repository/index"
	"github.com/tech/sendico/pkg/db/storable"
	"github.com/tech/sendico/pkg/mlogger"
	"github.com/tech/sendico/pkg/model"
	"github.com/tech/sendico/pkg/mservice"
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.uber.org/zap"
)

type CallbacksDB struct {
	auth.ProtectedDBImp[*model.Callback]
	auth.ArchivableDB[*model.Callback]
}

func Create(
	ctx context.Context,
	logger mlogger.Logger,
	enforcer auth.Enforcer,
	pdb policy.DB,
	db *mongo.Database,
) (*CallbacksDB, error) {
	p, err := auth.CreateDBImp[*model.Callback](ctx, logger, pdb, enforcer, mservice.Callbacks, db)
	if err != nil {
		return nil, err
	}

	for _, definition := range []*ri.Definition{
		{
			Name: "uq_callbacks_client_url",
			Keys: []ri.Key{
				{Field: storable.OrganizationRefField, Sort: ri.Asc},
				{Field: "organization_ref", Sort: ri.Asc},
				{Field: "url", Sort: ri.Asc},
			},
			Unique: true,
		},
		{
			Name: "idx_callbacks_lookup",
			Keys: []ri.Key{
				{Field: storable.OrganizationRefField, Sort: ri.Asc},
				{Field: "status", Sort: ri.Asc},
				{Field: "event_types", Sort: ri.Asc},
			},
		},
	} {
		if err := p.DBImp.Repository.CreateIndex(definition); err != nil {
			p.DBImp.Logger.Warn("Failed to create callbacks index", zap.String("index", definition.Name), zap.Error(err))
			return nil, err
		}
	}

	createEmpty := func() *model.Callback {
		return &model.Callback{}
	}
	getArchivable := func(callback *model.Callback) model.Archivable {
		return &callback.ArchivableBase
	}

	return &CallbacksDB{
		ProtectedDBImp: *p,
		ArchivableDB: auth.NewArchivableDB(
			p.DBImp,
			p.DBImp.Logger,
			enforcer,
			createEmpty,
			getArchivable,
		),
	}, nil
}

var _ callbacks.DB = (*CallbacksDB)(nil)
