// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.

package dal

import (
	"app/internal/models"
	"context"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"gorm.io/gorm/schema"

	"gorm.io/gen"
	"gorm.io/gen/field"

	"gorm.io/plugin/dbresolver"
)

func newComment(db *gorm.DB, opts ...gen.DOOption) comment {
	_comment := comment{}

	_comment.commentDo.UseDB(db, opts...)
	_comment.commentDo.UseModel(&models.Comment{})

	tableName := _comment.commentDo.TableName()
	_comment.ALL = field.NewAsterisk(tableName)
	_comment.Id = field.NewUint(tableName, "id")
	_comment.Text = field.NewString(tableName, "text")
	_comment.AuthorId = field.NewUint(tableName, "author_id")
	_comment.Author = commentHasOneAuthor{
		db: db.Session(&gorm.Session{}),

		RelationField: field.NewRelation("Author", "models.Author"),
		Posts: struct {
			field.RelationField
			Author struct {
				field.RelationField
			}
			PostType struct {
				field.RelationField
			}
			Comments struct {
				field.RelationField
				Author struct {
					field.RelationField
				}
				Posts struct {
					field.RelationField
				}
			}
		}{
			RelationField: field.NewRelation("Author.Posts", "models.Post"),
			Author: struct {
				field.RelationField
			}{
				RelationField: field.NewRelation("Author.Posts.Author", "models.Author"),
			},
			PostType: struct {
				field.RelationField
			}{
				RelationField: field.NewRelation("Author.Posts.PostType", "models.PostType"),
			},
			Comments: struct {
				field.RelationField
				Author struct {
					field.RelationField
				}
				Posts struct {
					field.RelationField
				}
			}{
				RelationField: field.NewRelation("Author.Posts.Comments", "models.Comment"),
				Author: struct {
					field.RelationField
				}{
					RelationField: field.NewRelation("Author.Posts.Comments.Author", "models.Author"),
				},
				Posts: struct {
					field.RelationField
				}{
					RelationField: field.NewRelation("Author.Posts.Comments.Posts", "models.Post"),
				},
			},
		},
		Comments: struct {
			field.RelationField
		}{
			RelationField: field.NewRelation("Author.Comments", "models.Comment"),
		},
	}

	_comment.Posts = commentManyToManyPosts{
		db: db.Session(&gorm.Session{}),

		RelationField: field.NewRelation("Posts", "models.Post"),
	}

	_comment.fillFieldMap()

	return _comment
}

type comment struct {
	commentDo

	ALL      field.Asterisk
	Id       field.Uint
	Text     field.String
	AuthorId field.Uint
	Author   commentHasOneAuthor

	Posts commentManyToManyPosts

	fieldMap map[string]field.Expr
}

func (c comment) Table(newTableName string) *comment {
	c.commentDo.UseTable(newTableName)
	return c.updateTableName(newTableName)
}

func (c comment) As(alias string) *comment {
	c.commentDo.DO = *(c.commentDo.As(alias).(*gen.DO))
	return c.updateTableName(alias)
}

func (c *comment) updateTableName(table string) *comment {
	c.ALL = field.NewAsterisk(table)
	c.Id = field.NewUint(table, "id")
	c.Text = field.NewString(table, "text")
	c.AuthorId = field.NewUint(table, "author_id")

	c.fillFieldMap()

	return c
}

func (c *comment) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
	_f, ok := c.fieldMap[fieldName]
	if !ok || _f == nil {
		return nil, false
	}
	_oe, ok := _f.(field.OrderExpr)
	return _oe, ok
}

func (c *comment) fillFieldMap() {
	c.fieldMap = make(map[string]field.Expr, 5)
	c.fieldMap["id"] = c.Id
	c.fieldMap["text"] = c.Text
	c.fieldMap["author_id"] = c.AuthorId

}

func (c comment) clone(db *gorm.DB) comment {
	c.commentDo.ReplaceConnPool(db.Statement.ConnPool)
	return c
}

func (c comment) replaceDB(db *gorm.DB) comment {
	c.commentDo.ReplaceDB(db)
	return c
}

type commentHasOneAuthor struct {
	db *gorm.DB

	field.RelationField

	Posts struct {
		field.RelationField
		Author struct {
			field.RelationField
		}
		PostType struct {
			field.RelationField
		}
		Comments struct {
			field.RelationField
			Author struct {
				field.RelationField
			}
			Posts struct {
				field.RelationField
			}
		}
	}
	Comments struct {
		field.RelationField
	}
}

func (a commentHasOneAuthor) Where(conds ...field.Expr) *commentHasOneAuthor {
	if len(conds) == 0 {
		return &a
	}

	exprs := make([]clause.Expression, 0, len(conds))
	for _, cond := range conds {
		exprs = append(exprs, cond.BeCond().(clause.Expression))
	}
	a.db = a.db.Clauses(clause.Where{Exprs: exprs})
	return &a
}

func (a commentHasOneAuthor) WithContext(ctx context.Context) *commentHasOneAuthor {
	a.db = a.db.WithContext(ctx)
	return &a
}

func (a commentHasOneAuthor) Session(session *gorm.Session) *commentHasOneAuthor {
	a.db = a.db.Session(session)
	return &a
}

func (a commentHasOneAuthor) Model(m *models.Comment) *commentHasOneAuthorTx {
	return &commentHasOneAuthorTx{a.db.Model(m).Association(a.Name())}
}

type commentHasOneAuthorTx struct{ tx *gorm.Association }

func (a commentHasOneAuthorTx) Find() (result *models.Author, err error) {
	return result, a.tx.Find(&result)
}

func (a commentHasOneAuthorTx) Append(values ...*models.Author) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Append(targetValues...)
}

func (a commentHasOneAuthorTx) Replace(values ...*models.Author) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Replace(targetValues...)
}

func (a commentHasOneAuthorTx) Delete(values ...*models.Author) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Delete(targetValues...)
}

func (a commentHasOneAuthorTx) Clear() error {
	return a.tx.Clear()
}

func (a commentHasOneAuthorTx) Count() int64 {
	return a.tx.Count()
}

type commentManyToManyPosts struct {
	db *gorm.DB

	field.RelationField
}

func (a commentManyToManyPosts) Where(conds ...field.Expr) *commentManyToManyPosts {
	if len(conds) == 0 {
		return &a
	}

	exprs := make([]clause.Expression, 0, len(conds))
	for _, cond := range conds {
		exprs = append(exprs, cond.BeCond().(clause.Expression))
	}
	a.db = a.db.Clauses(clause.Where{Exprs: exprs})
	return &a
}

func (a commentManyToManyPosts) WithContext(ctx context.Context) *commentManyToManyPosts {
	a.db = a.db.WithContext(ctx)
	return &a
}

func (a commentManyToManyPosts) Session(session *gorm.Session) *commentManyToManyPosts {
	a.db = a.db.Session(session)
	return &a
}

func (a commentManyToManyPosts) Model(m *models.Comment) *commentManyToManyPostsTx {
	return &commentManyToManyPostsTx{a.db.Model(m).Association(a.Name())}
}

type commentManyToManyPostsTx struct{ tx *gorm.Association }

func (a commentManyToManyPostsTx) Find() (result []*models.Post, err error) {
	return result, a.tx.Find(&result)
}

func (a commentManyToManyPostsTx) Append(values ...*models.Post) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Append(targetValues...)
}

func (a commentManyToManyPostsTx) Replace(values ...*models.Post) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Replace(targetValues...)
}

func (a commentManyToManyPostsTx) Delete(values ...*models.Post) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Delete(targetValues...)
}

func (a commentManyToManyPostsTx) Clear() error {
	return a.tx.Clear()
}

func (a commentManyToManyPostsTx) Count() int64 {
	return a.tx.Count()
}

type commentDo struct{ gen.DO }

type ICommentDo interface {
	gen.SubQuery
	Debug() ICommentDo
	WithContext(ctx context.Context) ICommentDo
	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
	ReplaceDB(db *gorm.DB)
	ReadDB() ICommentDo
	WriteDB() ICommentDo
	As(alias string) gen.Dao
	Session(config *gorm.Session) ICommentDo
	Columns(cols ...field.Expr) gen.Columns
	Clauses(conds ...clause.Expression) ICommentDo
	Not(conds ...gen.Condition) ICommentDo
	Or(conds ...gen.Condition) ICommentDo
	Select(conds ...field.Expr) ICommentDo
	Where(conds ...gen.Condition) ICommentDo
	Order(conds ...field.Expr) ICommentDo
	Distinct(cols ...field.Expr) ICommentDo
	Omit(cols ...field.Expr) ICommentDo
	Join(table schema.Tabler, on ...field.Expr) ICommentDo
	LeftJoin(table schema.Tabler, on ...field.Expr) ICommentDo
	RightJoin(table schema.Tabler, on ...field.Expr) ICommentDo
	Group(cols ...field.Expr) ICommentDo
	Having(conds ...gen.Condition) ICommentDo
	Limit(limit int) ICommentDo
	Offset(offset int) ICommentDo
	Count() (count int64, err error)
	Scopes(funcs ...func(gen.Dao) gen.Dao) ICommentDo
	Unscoped() ICommentDo
	Create(values ...*models.Comment) error
	CreateInBatches(values []*models.Comment, batchSize int) error
	Save(values ...*models.Comment) error
	First() (*models.Comment, error)
	Take() (*models.Comment, error)
	Last() (*models.Comment, error)
	Find() ([]*models.Comment, error)
	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*models.Comment, err error)
	FindInBatches(result *[]*models.Comment, batchSize int, fc func(tx gen.Dao, batch int) error) error
	Pluck(column field.Expr, dest interface{}) error
	Delete(...*models.Comment) (info gen.ResultInfo, err error)
	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
	Updates(value interface{}) (info gen.ResultInfo, err error)
	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
	UpdateFrom(q gen.SubQuery) gen.Dao
	Attrs(attrs ...field.AssignExpr) ICommentDo
	Assign(attrs ...field.AssignExpr) ICommentDo
	Joins(fields ...field.RelationField) ICommentDo
	Preload(fields ...field.RelationField) ICommentDo
	FirstOrInit() (*models.Comment, error)
	FirstOrCreate() (*models.Comment, error)
	FindByPage(offset int, limit int) (result []*models.Comment, count int64, err error)
	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
	Scan(result interface{}) (err error)
	Returning(value interface{}, columns ...string) ICommentDo
	UnderlyingDB() *gorm.DB
	schema.Tabler
}

func (c commentDo) Debug() ICommentDo {
	return c.withDO(c.DO.Debug())
}

func (c commentDo) WithContext(ctx context.Context) ICommentDo {
	return c.withDO(c.DO.WithContext(ctx))
}

func (c commentDo) ReadDB() ICommentDo {
	return c.Clauses(dbresolver.Read)
}

func (c commentDo) WriteDB() ICommentDo {
	return c.Clauses(dbresolver.Write)
}

func (c commentDo) Session(config *gorm.Session) ICommentDo {
	return c.withDO(c.DO.Session(config))
}

func (c commentDo) Clauses(conds ...clause.Expression) ICommentDo {
	return c.withDO(c.DO.Clauses(conds...))
}

func (c commentDo) Returning(value interface{}, columns ...string) ICommentDo {
	return c.withDO(c.DO.Returning(value, columns...))
}

func (c commentDo) Not(conds ...gen.Condition) ICommentDo {
	return c.withDO(c.DO.Not(conds...))
}

func (c commentDo) Or(conds ...gen.Condition) ICommentDo {
	return c.withDO(c.DO.Or(conds...))
}

func (c commentDo) Select(conds ...field.Expr) ICommentDo {
	return c.withDO(c.DO.Select(conds...))
}

func (c commentDo) Where(conds ...gen.Condition) ICommentDo {
	return c.withDO(c.DO.Where(conds...))
}

func (c commentDo) Order(conds ...field.Expr) ICommentDo {
	return c.withDO(c.DO.Order(conds...))
}

func (c commentDo) Distinct(cols ...field.Expr) ICommentDo {
	return c.withDO(c.DO.Distinct(cols...))
}

func (c commentDo) Omit(cols ...field.Expr) ICommentDo {
	return c.withDO(c.DO.Omit(cols...))
}

func (c commentDo) Join(table schema.Tabler, on ...field.Expr) ICommentDo {
	return c.withDO(c.DO.Join(table, on...))
}

func (c commentDo) LeftJoin(table schema.Tabler, on ...field.Expr) ICommentDo {
	return c.withDO(c.DO.LeftJoin(table, on...))
}

func (c commentDo) RightJoin(table schema.Tabler, on ...field.Expr) ICommentDo {
	return c.withDO(c.DO.RightJoin(table, on...))
}

func (c commentDo) Group(cols ...field.Expr) ICommentDo {
	return c.withDO(c.DO.Group(cols...))
}

func (c commentDo) Having(conds ...gen.Condition) ICommentDo {
	return c.withDO(c.DO.Having(conds...))
}

func (c commentDo) Limit(limit int) ICommentDo {
	return c.withDO(c.DO.Limit(limit))
}

func (c commentDo) Offset(offset int) ICommentDo {
	return c.withDO(c.DO.Offset(offset))
}

func (c commentDo) Scopes(funcs ...func(gen.Dao) gen.Dao) ICommentDo {
	return c.withDO(c.DO.Scopes(funcs...))
}

func (c commentDo) Unscoped() ICommentDo {
	return c.withDO(c.DO.Unscoped())
}

func (c commentDo) Create(values ...*models.Comment) error {
	if len(values) == 0 {
		return nil
	}
	return c.DO.Create(values)
}

func (c commentDo) CreateInBatches(values []*models.Comment, batchSize int) error {
	return c.DO.CreateInBatches(values, batchSize)
}

// Save : !!! underlying implementation is different with GORM
// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
func (c commentDo) Save(values ...*models.Comment) error {
	if len(values) == 0 {
		return nil
	}
	return c.DO.Save(values)
}

func (c commentDo) First() (*models.Comment, error) {
	if result, err := c.DO.First(); err != nil {
		return nil, err
	} else {
		return result.(*models.Comment), nil
	}
}

func (c commentDo) Take() (*models.Comment, error) {
	if result, err := c.DO.Take(); err != nil {
		return nil, err
	} else {
		return result.(*models.Comment), nil
	}
}

func (c commentDo) Last() (*models.Comment, error) {
	if result, err := c.DO.Last(); err != nil {
		return nil, err
	} else {
		return result.(*models.Comment), nil
	}
}

func (c commentDo) Find() ([]*models.Comment, error) {
	result, err := c.DO.Find()
	return result.([]*models.Comment), err
}

func (c commentDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*models.Comment, err error) {
	buf := make([]*models.Comment, 0, batchSize)
	err = c.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
		defer func() { results = append(results, buf...) }()
		return fc(tx, batch)
	})
	return results, err
}

func (c commentDo) FindInBatches(result *[]*models.Comment, batchSize int, fc func(tx gen.Dao, batch int) error) error {
	return c.DO.FindInBatches(result, batchSize, fc)
}

func (c commentDo) Attrs(attrs ...field.AssignExpr) ICommentDo {
	return c.withDO(c.DO.Attrs(attrs...))
}

func (c commentDo) Assign(attrs ...field.AssignExpr) ICommentDo {
	return c.withDO(c.DO.Assign(attrs...))
}

func (c commentDo) Joins(fields ...field.RelationField) ICommentDo {
	for _, _f := range fields {
		c = *c.withDO(c.DO.Joins(_f))
	}
	return &c
}

func (c commentDo) Preload(fields ...field.RelationField) ICommentDo {
	for _, _f := range fields {
		c = *c.withDO(c.DO.Preload(_f))
	}
	return &c
}

func (c commentDo) FirstOrInit() (*models.Comment, error) {
	if result, err := c.DO.FirstOrInit(); err != nil {
		return nil, err
	} else {
		return result.(*models.Comment), nil
	}
}

func (c commentDo) FirstOrCreate() (*models.Comment, error) {
	if result, err := c.DO.FirstOrCreate(); err != nil {
		return nil, err
	} else {
		return result.(*models.Comment), nil
	}
}

func (c commentDo) FindByPage(offset int, limit int) (result []*models.Comment, count int64, err error) {
	result, err = c.Offset(offset).Limit(limit).Find()
	if err != nil {
		return
	}

	if size := len(result); 0 < limit && 0 < size && size < limit {
		count = int64(size + offset)
		return
	}

	count, err = c.Offset(-1).Limit(-1).Count()
	return
}

func (c commentDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
	count, err = c.Count()
	if err != nil {
		return
	}

	err = c.Offset(offset).Limit(limit).Scan(result)
	return
}

func (c commentDo) Scan(result interface{}) (err error) {
	return c.DO.Scan(result)
}

func (c commentDo) Delete(models ...*models.Comment) (result gen.ResultInfo, err error) {
	return c.DO.Delete(models)
}

func (c *commentDo) withDO(do gen.Dao) *commentDo {
	c.DO = *do.(*gen.DO)
	return c
}
