package account

import (
	"context"

	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/metric"
	"go.opentelemetry.io/otel/metric/noop"
)

// meterName scopes the account domain's OpenTelemetry instruments.
const meterName = "scrabble/backend/account"

// kindGuest labels guest accounts in accounts_created_total. Guests carry no
// identity, so they have no identity Kind; this is the metric label for them.
const kindGuest = "guest"

// accountMetrics holds the account domain's operational instruments. It defaults
// to no-ops (see defaultAccountMetrics); SetMetrics installs the real meter during
// startup wiring.
type accountMetrics struct {
	created metric.Int64Counter
}

// defaultAccountMetrics returns instruments backed by a no-op meter.
func defaultAccountMetrics() *accountMetrics {
	return newAccountMetrics(noop.NewMeterProvider().Meter(meterName))
}

// newAccountMetrics builds the instruments on meter, falling back to a no-op
// counter on the (rare) construction error.
func newAccountMetrics(meter metric.Meter) *accountMetrics {
	c, err := meter.Int64Counter("accounts_created_total",
		metric.WithDescription("New accounts created, labelled by kind (telegram/email/guest); robots are not counted."))
	if err != nil {
		c, _ = noop.NewMeterProvider().Meter(meterName).Int64Counter("accounts_created_total")
	}
	return &accountMetrics{created: c}
}

// SetMetrics installs the meter the account store records to. It must be called
// during startup wiring; the default is a no-op meter.
func (s *Store) SetMetrics(meter metric.Meter) {
	if meter == nil {
		return
	}
	s.metrics = newAccountMetrics(meter)
}

// recordCreated counts one newly created account of the given kind.
func (m *accountMetrics) recordCreated(ctx context.Context, kind string) {
	m.created.Add(ctx, 1, metric.WithAttributes(attribute.String("kind", kind)))
}
