package observability

import (
	"context"
	"time"

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

func (o *ObservabilityDB) AuthorizedFieldPublisherGrantCreate(ctx context.Context, grant *db.AuthorizedFieldPublisherGrant) (int, error) {
	var err error
	var id int
	o.observe(ctx, "AuthorizedFieldPublisherGrantCreate",
		func() ([]zap.Field, error) {
			id, err = o.db.AuthorizedFieldPublisherGrantCreate(ctx, grant)
			cpy := *grant
			cpy.ID = id
			return []zap.Field{
				zap.Object("authorizedField", cpy),
			}, err
		})
	return id, err
}

func (o *ObservabilityDB) AuthorizedFieldPublisherGrant(ctx context.Context, iamRoleID, eventStreamID int) (*db.AuthorizedFieldPublisherGrant, error) {
	var err error
	var grant *db.AuthorizedFieldPublisherGrant
	o.observe(ctx, "AuthorizedFieldPublisherGrant",
		func() ([]zap.Field, error) {
			grant, err = o.db.AuthorizedFieldPublisherGrant(ctx, iamRoleID, eventStreamID)
			return []zap.Field{
				zap.Int("iamRoleID", iamRoleID),
				zap.Int("eventStreamID", eventStreamID),
			}, err
		})
	return grant, err
}

func (o *ObservabilityDB) AuthorizedFieldPublisherGrants(ctx context.Context) ([]*db.AuthorizedFieldPublisherGrant, error) {
	var err error
	var grants []*db.AuthorizedFieldPublisherGrant
	o.observe(ctx, "AuthorizedFieldPublisherGrants",
		func() ([]zap.Field, error) {
			grants, err = o.db.AuthorizedFieldPublisherGrants(ctx)
			return []zap.Field{}, err
		})
	return grants, err
}

func (o *ObservabilityDB) AuthorizedFieldPublisherGrantByID(ctx context.Context, id int) (*db.AuthorizedFieldPublisherGrant, error) {
	var err error
	var grant *db.AuthorizedFieldPublisherGrant
	o.observe(ctx, "AuthorizedFieldPublisherGrantByID",
		func() ([]zap.Field, error) {
			grant, err = o.db.AuthorizedFieldPublisherGrantByID(ctx, id)
			return []zap.Field{
				zap.Int("authorizedFieldPublisherGrantID", id),
			}, err
		})
	return grant, err
}

func (o *ObservabilityDB) AuthorizedFieldPublisherGrantsByIAMRoleID(ctx context.Context, iamRoleID int) ([]*db.AuthorizedFieldPublisherGrant, error) {
	var err error
	var grants []*db.AuthorizedFieldPublisherGrant
	o.observe(ctx, "AuthorizedFieldsByIAMRoleID",
		func() ([]zap.Field, error) {
			grants, err = o.db.AuthorizedFieldPublisherGrantsByIAMRoleID(ctx, iamRoleID)
			return []zap.Field{
				zap.Int("iamRoleID", iamRoleID),
			}, err
		})
	return grants, err
}

func (o *ObservabilityDB) AuthorizedFieldPublisherGrantsByEventStreamID(ctx context.Context, eventStreamID int) ([]*db.AuthorizedFieldPublisherGrant, error) {
	var err error
	var grants []*db.AuthorizedFieldPublisherGrant
	o.observe(ctx, "AuthorizedFieldPublisherGrantsByEventStreamID",
		func() ([]zap.Field, error) {
			grants, err = o.db.AuthorizedFieldPublisherGrantsByEventStreamID(ctx, eventStreamID)
			return []zap.Field{
				zap.Int("eventStreamID", eventStreamID),
			}, err
		})
	return grants, err
}

func (o *ObservabilityDB) AuthorizedFieldPublisherGrantDeleteByID(ctx context.Context, id int) error {
	var err error
	o.observe(ctx, "AuthorizedFieldPublisherGrantDeleteByID",
		func() ([]zap.Field, error) {
			err = o.db.AuthorizedFieldPublisherGrantDeleteByID(ctx, id)
			return []zap.Field{
				zap.Int("id", id),
			}, err
		})
	return err
}

func (o *ObservabilityDB) AuthorizedFieldPublisherGrantUpdateInfra(ctx context.Context, l db.AWSLease, id int, update *db.AuthorizedFieldPublisherGrantInfraUpdate) (int, error) {
	var err error
	var i int
	o.observe(ctx, "AuthorizedFieldPublisherGrantUpdateInfra",
		func() ([]zap.Field, error) {
			i, err = o.db.AuthorizedFieldPublisherGrantUpdateInfra(ctx, l, id, update)
			return []zap.Field{
				zap.Int("authorizedFieldPublisherGrantID", id),
				zap.Object("authorizedFieldPublisherGrantInfraUpdate", update),
				zap.Object("lease", l),
			}, err
		})
	return i, err
}

func (o *ObservabilityDB) AuthorizedFieldPublisherGrantAcquireLease(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, "AuthorizedFieldPublisherGrantAcquireLease",
		func() ([]zap.Field, error) {
			var fields []zap.Field
			awsLease, retCtx, err = o.db.AuthorizedFieldPublisherGrantAcquireLease(ctx, resourceID, timeout)
			if awsLease != nil {
				fields = append(fields, zap.Object("lease", awsLease))
			}
			return append(fields, zap.Int("authorizedFieldPublisherGrantID", resourceID)), err
		},
	)
	return awsLease, retCtx, err
}

func (o *ObservabilityDB) AuthorizedFieldPublisherGrantReleaseLease(lease db.AWSLease) error {
	// This operation doesn't pass a context so it can't go thru this middleware
	return o.db.EventStreamReleaseLease(lease)
}
