package repo

import (
	"context"

	jmpent "github.com/tidbcloud/devops/entity/jump"
	"github.com/tidbcloud/devops/pkg/infra/utils/repoopt"
	"github.com/tidbcloud/devops/pkg/service/jump/repo/cvt"

	"github.com/tidbcloud/pkgv2/db"
)

type (
	PatchAuthorization func(current *jmpent.Authorization) error
)

type JumpRepo interface {
	// Instances
	ListAuthorizations(ctx context.Context, opts ...repoopt.Option) ([]*jmpent.Authorization, error)
	GetAuthorization(ctx context.Context, id uint64) (*jmpent.Authorization, error)
	CreateAuthorization(ctx context.Context, auth *jmpent.Authorization) (*jmpent.Authorization, error)
	PatchAuthorization(ctx context.Context, current *jmpent.Authorization, patch ...PatchAuthorization) error
	CountAuthorization(ctx context.Context, opts ...repoopt.Option) (int64, error)
}

func NewJumpRepo(dbp db.Provider) JumpRepo {
	driver := &driver{
		cvter:      cvt.NewConverter(),
		dbProvider: dbp,
	}

	return &repo{
		authDriver: (*authorizationDriver)(driver),
	}
}

type driver struct {
	cvter      *cvt.Converter
	dbProvider db.Provider
}

type repo struct {
	authDriver AuthorizationDriver
}

func (r *repo) ListAuthorizations(ctx context.Context, opts ...repoopt.Option) ([]*jmpent.Authorization, error) {
	return r.authDriver.Query(ctx, opts...)
}

func (r *repo) GetAuthorization(ctx context.Context, id uint64) (*jmpent.Authorization, error) {
	return r.authDriver.Load(ctx, id)
}

func (r *repo) CreateAuthorization(ctx context.Context, authorization *jmpent.Authorization) (*jmpent.Authorization, error) {
	// validate
	/*err := validation.Operation.Instance(instance)
	if err != nil {
		return nil, err
	}*/

	return r.authDriver.Save(ctx, authorization)
}

func (r *repo) PatchAuthorization(ctx context.Context, current *jmpent.Authorization, patch ...PatchAuthorization) error {
	for _, p := range patch {
		err := p(current)
		if err != nil {
			return err
		}
	}

	/*err := validation.Operation.Instance(current)
	if err != nil {
		return err
	}*/

	_, err := r.authDriver.Save(ctx, current)
	return err
}

func (r *repo) CountAuthorization(ctx context.Context, opts ...repoopt.Option) (int64, error) {
	return r.authDriver.Count(ctx, opts...)
}
