package db

import (
	"context"
	"database/sql"
	"time"

	"go.uber.org/zap/zapcore"
)

type AuthorizedFieldSubscriberGrant struct {
	ID                int           `json:"id" db:"id"`
	IAMRoleID         int           `json:"iam_role_id" db:"iam_role_id"`
	AuthorizedFieldID int           `json:"authorized_field_id" db:"authorized_field_id"`
	KMSGrantID        string        `json:"kms_grant_id" db:"kms_grant_id"`
	AWSLeaseID        sql.NullInt64 `json:"aws_lease_id" db:"aws_lease_id"`
}

func (a AuthorizedFieldSubscriberGrant) MarshalLogObject(enc zapcore.ObjectEncoder) error {
	enc.AddInt("id", a.ID)
	enc.AddInt("authorizedFieldID", a.AuthorizedFieldID)
	enc.AddInt("iamRoleID", a.IAMRoleID)
	return nil
}

type AuthorizedFieldSubscriberGrantInfraUpdate struct {
	KMSGrantID string
}

func (a AuthorizedFieldSubscriberGrantInfraUpdate) MarshalLogObject(enc zapcore.ObjectEncoder) error {
	enc.AddString("kmsGrantID", a.KMSGrantID)
	return nil
}

type AuthorizedFieldSubscriberGrantDB interface {
	AuthorizedFieldSubscriberGrants(ctx context.Context) ([]*AuthorizedFieldSubscriberGrant, error)
	AuthorizedFieldSubscriberGrant(ctx context.Context, iamRoleID, authorizedFieldID int) (*AuthorizedFieldSubscriberGrant, error)
	AuthorizedFieldSubscriberGrantByID(ctx context.Context, id int) (*AuthorizedFieldSubscriberGrant, error)
	AuthorizedFieldSubscriberGrantsByIAMRoleID(ctx context.Context, iamRoleID int) ([]*AuthorizedFieldSubscriberGrant, error)
	AuthorizedFieldSubscriberGrantsByAuthorizedField(ctx context.Context, authedFieldID int) ([]*AuthorizedFieldSubscriberGrant, error)
	// TODO: do we need additional access patterns? Remains to be seen until converger logic implemented
	//AuthorizedFieldSubscriberGrantsByEventStreamID(ctx context.Context, eventStreamID int) ([]*AuthorizedFieldSubscriberGrant, error)
	//AuthorizedFieldSubscriberGrantsByAuthorizedFieldID(ctx context.Context, authorizedFieldID int) ([]*AuthorizedFieldSubscriberGrant, error)
	AuthorizedFieldSubscriberGrantDeleteByID(ctx context.Context, id int) error

	AuthorizedFieldSubscriberGrantCreate(ctx context.Context, grant *AuthorizedFieldSubscriberGrant) (int, error)
	AuthorizedFieldSubscriberGrantUpdateInfra(ctx context.Context, lease AWSLease, id int, grantUpdateInfra *AuthorizedFieldSubscriberGrantInfraUpdate) (int, error)

	AuthorizedFieldSubscriberGrantAcquireLease(ctx context.Context, resourceID int, timeout time.Duration) (AWSLease, context.Context, error)
	AuthorizedFieldSubscriberGrantReleaseLease(lease AWSLease) error
}
