package permissions

import (
	"context"
	"time"

	"github.com/nexuscrm/kernel/pkg/telemetry"
	"github.com/nexuscrm/shared/pkg/models"
	"github.com/rs/zerolog/log"
)

type recordAccessPhaseProfileKey struct{}

// WithRecordAccessPhaseProfile enables one bounded, request-local breakdown of
// the aggregate Read/Edit/Delete decision. It is deliberately opt-in so list
// and mutation callers do not pay for diagnostic counters or emit per-record
// logs. Runtime record-view is the owning caller because it already exposes a
// phase profile and needs to distinguish dynamic authority work from record
// hydration.
func WithRecordAccessPhaseProfile(ctx context.Context) context.Context {
	if ctx == nil {
		ctx = context.Background()
	}
	return context.WithValue(ctx, recordAccessPhaseProfileKey{}, true)
}

type recordAccessPhaseObservation struct {
	name       string
	elapsed    time.Duration
	sqlCount   uint64
	sqlElapsed time.Duration
	sqlMax     time.Duration
}

type recordAccessPhaseProfile struct {
	enabled      bool
	observations []recordAccessPhaseObservation
}

func newRecordAccessPhaseProfile(ctx context.Context) *recordAccessPhaseProfile {
	enabled, _ := ctx.Value(recordAccessPhaseProfileKey{}).(bool)
	return &recordAccessPhaseProfile{enabled: enabled}
}

func (p *recordAccessPhaseProfile) bool(ctx context.Context, name string, evaluate func(context.Context) bool) bool {
	if p == nil || !p.enabled {
		return evaluate(ctx)
	}
	observedCtx, counter := telemetry.WithSQLStatementCounter(ctx)
	started := time.Now()
	result := evaluate(observedCtx)
	p.observations = append(p.observations, recordAccessPhaseObservation{
		name:       name,
		elapsed:    time.Since(started),
		sqlCount:   counter.Count(),
		sqlElapsed: counter.TotalDuration(),
		sqlMax:     counter.MaxDuration(),
	})
	return result
}

func (p *recordAccessPhaseProfile) emit(schema *models.ObjectMetadata, user *models.UserSession) {
	if p == nil || !p.enabled {
		return
	}
	event := log.Debug().Str("event", "record_access_all_phase_profile")
	if schema != nil {
		event = event.Str("object", schema.APIName)
	}
	if user != nil {
		event = event.Str("user", user.ID)
	}
	for _, observation := range p.observations {
		event = event.
			Uint64(observation.name+"_sql", observation.sqlCount).
			Int64(observation.name+"_sql_elapsed_ms", observation.sqlElapsed.Milliseconds()).
			Int64(observation.name+"_sql_max_ms", observation.sqlMax.Milliseconds()).
			Int64(observation.name+"_elapsed_ms", observation.elapsed.Milliseconds())
	}
	event.Msg("Aggregate record-access phase profile")
}
