package observability

import (
	"context"
	"time"

	"code.justin.tv/eventbus/controlplane/internal/db"
	"go.uber.org/zap"
)

func (o *ObservabilityDB) EventStreamCreate(ctx context.Context, eventStream *db.EventStream) (int, error) {
	var err error
	var id int
	o.observe(ctx, "EventStreamCreate",
		func() ([]zap.Field, error) {
			id, err = o.db.EventStreamCreate(ctx, eventStream)
			cpy := *eventStream
			cpy.ID = id
			return []zap.Field{
				zap.Object("eventStream", cpy),
			}, err
		})
	return id, err
}
func (o *ObservabilityDB) EventStreamUpdate(ctx context.Context, id int, eventStreamEditable *db.EventStreamEditable) (int, error) {
	var err error
	var retID int
	o.observe(ctx, "EventStreamUpdate",
		func() ([]zap.Field, error) {
			retID, err = o.db.EventStreamUpdate(ctx, id, eventStreamEditable)
			return []zap.Field{
				zap.Int("eventStreamID", id),
				zap.Object("eventStreamUpdate", eventStreamEditable), // doesn't actually do anything
			}, err
		})
	return retID, err
}
func (o *ObservabilityDB) EventStreamUpdateInfra(ctx context.Context, lease db.AWSLease, id int, eventStreamInfraUpdate *db.EventStreamInfraUpdate) (int, error) {
	var err error
	var retID int
	o.observe(ctx, "EventStreamUpdateInfra",
		func() ([]zap.Field, error) {
			id, err = o.db.EventStreamUpdateInfra(ctx, lease, id, eventStreamInfraUpdate)
			return []zap.Field{
				zap.Object("eventStreamInfraUpdate", eventStreamInfraUpdate),
				zap.Int("eventStreamID", id),
				zap.Object("lease", lease),
			}, err
		})
	return retID, err
}
func (o *ObservabilityDB) EventStreamDeleteByEventTypeID(ctx context.Context, eventTypeID int) (int, error) {
	var err error
	var numDeleted int
	o.observe(ctx, "EventStreamDeleteByEventTypeID",
		func() ([]zap.Field, error) {
			numDeleted, err = o.db.EventStreamDeleteByEventTypeID(ctx, eventTypeID)
			return []zap.Field{
				zap.Int("eventTypeID", eventTypeID),
			}, err
		})
	return numDeleted, err
}
func (o *ObservabilityDB) EventStreams(ctx context.Context) ([]*db.EventStream, error) {
	var err error
	var eventStreams []*db.EventStream
	o.observe(ctx, "EventStreams",
		func() ([]zap.Field, error) {
			eventStreams, err = o.db.EventStreams(ctx)
			return []zap.Field{}, err
		})
	return eventStreams, err
}
func (o *ObservabilityDB) EventStreamsByEnvironment(ctx context.Context, environment string) ([]*db.EventStream, error) {
	var err error
	var eventStreams []*db.EventStream
	o.observe(ctx, "EventStreamsByEnvironment",
		func() ([]zap.Field, error) {
			eventStreams, err = o.db.EventStreamsByEnvironment(ctx, environment)
			return []zap.Field{
				zap.String("environment", environment),
			}, err
		})
	return eventStreams, err
}

func (o *ObservabilityDB) EventStreamsByName(ctx context.Context, name string) ([]*db.EventStream, error) {
	var err error
	var eventStreams []*db.EventStream
	o.observe(ctx, "EventStreamsByName",
		func() ([]zap.Field, error) {
			eventStreams, err = o.db.EventStreamsByName(ctx, name)
			return []zap.Field{
				zap.String("name", name),
			}, err
		})
	return eventStreams, err
}

func (o *ObservabilityDB) EventStreamsByEventTypeID(ctx context.Context, eventTypeID int) ([]*db.EventStream, error) {
	return o.db.EventStreamsByEventTypeID(ctx, eventTypeID) //STUB
}

func (o *ObservabilityDB) EventStreamByID(ctx context.Context, id int) (*db.EventStream, error) {
	var err error
	var eventStream *db.EventStream
	o.observe(ctx, "EventStreamByID",
		func() ([]zap.Field, error) {
			eventStream, err = o.db.EventStreamByID(ctx, id)
			return []zap.Field{
				zap.Int("eventStreamID", id),
			}, err
		})
	return eventStream, err
}
func (o *ObservabilityDB) EventStreamByNameAndEnvironment(ctx context.Context, name, environment string) (*db.EventStream, error) {
	var err error
	var eventStream *db.EventStream
	o.observe(ctx, "EventStreamByNameAndEnvironment",
		func() ([]zap.Field, error) {
			eventStream, err = o.db.EventStreamByNameAndEnvironment(ctx, name, environment)
			return []zap.Field{
				zap.String("eventTypeName", name),
				zap.String("environment", environment),
			}, err
		})
	return eventStream, err
}
func (o *ObservabilityDB) EventStreamAcquireLease(ctx context.Context, resourceID int, timeout time.Duration) (db.AWSLease, context.Context, error) {
	var err error
	var awsLease db.AWSLease
	var retCtx context.Context
	o.observe(ctx, "EventStreamAcquireLease",
		func() ([]zap.Field, error) {
			var fields []zap.Field
			awsLease, retCtx, err = o.db.EventStreamAcquireLease(ctx, resourceID, timeout)
			if awsLease != nil {
				fields = append(fields, zap.Object("lease", awsLease))
			}
			return append(fields, zap.Int("eventStreamID", resourceID)), err
		},
	)
	return awsLease, retCtx, err
}
func (o *ObservabilityDB) EventStreamReleaseLease(lease db.AWSLease) error {
	// This operation doesn't pass a context so it can't go thru this middleware
	return o.db.EventStreamReleaseLease(lease)
}
