package repo

import (
	"context"
	"errors"

	privent "github.com/tidbcloud/devops/entity/privilege"
	"github.com/tidbcloud/devops/entity/validation"
	"github.com/tidbcloud/devops/pkg/infra/utils/repoopt"
	"github.com/tidbcloud/devops/pkg/service/privilege/repo/cvt"

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

type Repo interface {
	Get(ctx context.Context, id uint64) (*privent.Privilege, error)
	List(ctx context.Context, opts ...repoopt.Option) ([]*privent.Privilege, error)
	Create(ctx context.Context, item *privent.Privilege) (*privent.Privilege, error)
	Update(ctx context.Context, item *privent.Privilege) (*privent.Privilege, error)
	Count(ctx context.Context, opts ...repoopt.Option) (int64, error)
	Options() opts
}

func NewRepo(dbp db.Provider) Repo {
	cvt := cvt.NewConverter()

	return &repo{
		driver: &driver{
			cvter:      cvt,
			dbProvider: dbp,
		},
	}
}

type repo struct {
	driver Driver
}

func (r *repo) Get(ctx context.Context, id uint64) (*privent.Privilege, error) {
	return r.driver.Load(ctx, id)
}

func (r *repo) List(ctx context.Context, opts ...repoopt.Option) ([]*privent.Privilege, error) {
	return r.driver.Query(ctx, opts...)
}

func (r *repo) Create(ctx context.Context, item *privent.Privilege) (*privent.Privilege, error) {
	if item.ID != 0 {
		return nil, errors.New("id must be 0 when create")
	}

	err := validation.Privilege.Privilege(item)
	if err != nil {
		return nil, err
	}

	return r.driver.Save(ctx, item)
}

func (r *repo) Update(ctx context.Context, item *privent.Privilege) (*privent.Privilege, error) {
	if item.ID == 0 {
		return nil, errors.New("id must not be 0 when update")
	}

	err := validation.Privilege.Privilege(item)
	if err != nil {
		return nil, err
	}

	return r.driver.Save(ctx, item)
}

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

func (r *repo) Options() opts {
	return opts{}
}
