package confirmationdb

import (
	"github.com/tech/sendico/pkg/db/confirmation"
	ri "github.com/tech/sendico/pkg/db/repository/index"
	"github.com/tech/sendico/pkg/db/template"
	"github.com/tech/sendico/pkg/mlogger"
	"github.com/tech/sendico/pkg/model"
	"github.com/tech/sendico/pkg/mservice"
	"go.mongodb.org/mongo-driver/mongo"
	"go.uber.org/zap"
)

const (
	fieldAccountRef  = "accountRef"
	fieldDestination = "destination"
	fieldTarget      = "target"
	fieldExpiresAt   = "expiresAt"
	fieldUsed        = "used"
)

type ConfirmationDB struct {
	template.DBImp[*model.ConfirmationCode]
}

func Create(logger mlogger.Logger, db *mongo.Database) (confirmation.DB, error) {
	p := &ConfirmationDB{
		DBImp: *template.Create[*model.ConfirmationCode](logger, mservice.Confirmations, db),
	}

	// Ensure one active code per account/destination/target.
	if err := p.Repository.CreateIndex(&ri.Definition{
		Keys: []ri.Key{
			{Field: fieldAccountRef, Sort: ri.Asc},
			{Field: fieldDestination, Sort: ri.Asc},
			{Field: fieldTarget, Sort: ri.Asc},
		},
		Unique: true,
	}); err != nil {
		p.Logger.Error("Failed to create confirmation unique index", zap.Error(err))
		return nil, err
	}

	// TTL on expiry.
	ttl := int32(0)
	if err := p.Repository.CreateIndex(&ri.Definition{
		Keys: []ri.Key{
			{Field: fieldExpiresAt, Sort: ri.Asc},
		},
		TTL: &ttl,
	}); err != nil {
		p.Logger.Error("Failed to create confirmation TTL index", zap.Error(err))
		return nil, err
	}

	// Query helper indexes.
	if err := p.Repository.CreateIndex(&ri.Definition{
		Keys: []ri.Key{
			{Field: fieldUsed, Sort: ri.Asc},
		},
	}); err != nil {
		p.Logger.Error("Failed to create confirmation used index", zap.Error(err))
		return nil, err
	}

	return p, nil
}
