package observability

import (
	"context"
	"time"

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

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

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

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

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

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

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

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

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

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

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