package repository

import (
	"cron_admin/app/http/entities"
	"cron_admin/app/models"
	"github.com/pkg/errors"
	"github.com/qit-team/snow-core/db"

	"time"
	"xorm.io/xorm"
)

type CommonRepo[P models.PO] struct {
	repo *xorm.Session
}

type ICommonRepo[P models.PO] interface {
	GetSession() *xorm.Session
	FindAll(list *[]P, opts ...DBOption) error
	FindAndCount(list *[]P, opts ...DBOption) (int64, error)
	Get(db *P, opts ...DBOption) (bool, error)
	Update(db *P, opts ...DBOption) (int64, error)
	Delete(db *P, opts ...DBOption) (int64, error)
	InsertOne(db *P, opts ...DBOption) (int64, error)
	InsertBatch(db *[]P, opts ...DBOption) (int64, error)

	WithSession(session *xorm.Session) ICommonRepo[P]
	WithByID(id uint) DBOption
	WithByDate(startTime, endTime time.Time) DBOption
	WithByUpdateDate(startTime, endTime time.Time) DBOption
	WithByStartDate(startTime time.Time) DBOption
	WithByEndDate(startTime time.Time) DBOption
	WithDesc(orderStr string) DBOption
	WithByStatus(status int) DBOption
	WithIdsIn(ids []uint) DBOption
	WithPage(pageFilter entities.PageRequest) DBOption
}

func NewCommonRepo[P models.PO]() ICommonRepo[P] {
	return &CommonRepo[P]{}
}

func (this *CommonRepo[P]) WithSession(session *xorm.Session) ICommonRepo[P] {
	this.repo = session
	return this
}

func (this *CommonRepo[P]) GetSession() *xorm.Session {
	return this.repo
}

func (this *CommonRepo[P]) FindAll(list *[]P, opts ...DBOption) error {
	return getDb(this.repo, opts...).Find(list)
}

func (this *CommonRepo[P]) FindAndCount(list *[]P, opts ...DBOption) (int64, error) {
	return getDb(this.repo, opts...).FindAndCount(list)
}

func (this *CommonRepo[P]) Get(db *P, opts ...DBOption) (bool, error) {
	return getDb(this.repo, opts...).Get(db)
}

func (this *CommonRepo[P]) Update(db *P, opts ...DBOption) (int64, error) {
	if len(opts) == 0 {
		return 0, errors.New("不允许不带条件的更新")
	}
	return getDb(this.repo, opts...).Update(db)
}

// 不允许不带条件的删除
func (this *CommonRepo[P]) Delete(db *P, opts ...DBOption) (int64, error) {
	if len(opts) == 0 {
		return 0, errors.New("不允许不带条件的删除")
	}
	return getDb(this.repo, opts...).Delete(db)
}

func (this *CommonRepo[P]) InsertOne(db *P, opts ...DBOption) (int64, error) {
	return getDb(this.repo, opts...).Insert(db)
}

// 批量插入
func (this *CommonRepo[P]) InsertBatch(db *[]P, opts ...DBOption) (int64, error) {
	return getDb(this.repo, opts...).Insert(db)
}

func getDb(repo *xorm.Session, opts ...DBOption) *xorm.Session {
	if repo == nil {
		repo = db.GetDb().NewSession()
	}
	for _, opt := range opts {
		repo = opt(repo)
	}
	return repo
}