package repository

import (
	"github.com/tech/sendico/pkg/db/internal/mongo/repositoryimp/builderimp"
	"github.com/tech/sendico/pkg/db/repository/builder"
	"github.com/tech/sendico/pkg/db/storable"
	"github.com/tech/sendico/pkg/model"
	"go.mongodb.org/mongo-driver/v2/bson"
)

func Query() builder.Query {
	return builderimp.NewQueryImp()
}

func Filter(field string, value any) builder.Query {
	return Query().Filter(Field(field), value)
}

func Field(baseName string) builder.Field {
	return builderimp.NewFieldImp(baseName)
}

func Ref(field builder.Field) builder.Field {
	return builderimp.NewRefFieldImp(field)
}

func RootRef() builder.Field {
	return builderimp.NewRootRef()
}

func RemoveRef() builder.Field {
	return builderimp.NewRemoveRef()
}

func Pipeline() builder.Pipeline {
	return builderimp.NewPipelineImp()
}

func IDField() builder.Field {
	return Field(storable.IDField)
}

func NameField() builder.Field {
	return Field(model.NameField)
}

func DescrtiptionField() builder.Field {
	return Field(model.DescriptionField)
}

func IsArchivedField() builder.Field {
	return Field(storable.IsArchivedField)
}

func IDFilter(ref bson.ObjectID) builder.Query {
	return Query().Filter(IDField(), ref)
}

func ArchivedFilter() builder.Query {
	return IsArchivedFilter(true)
}

func NotArchivedFilter() builder.Query {
	return IsArchivedFilter(false)
}

func IsArchivedFilter(isArchived bool) builder.Query {
	return Query().Filter(IsArchivedField(), isArchived)
}

func OrgField() builder.Field {
	return Field(storable.OrganizationRefField)
}

func OrgFilter(ref bson.ObjectID) builder.Query {
	return Query().Filter(OrgField(), ref)
}

func ProjectField() builder.Field {
	return Field("projectRef")
}

func ProjectFilter(ref bson.ObjectID) builder.Query {
	return Query().Filter(ProjectField(), ref)
}

func AccountField() builder.Field {
	return Field(model.AccountRefField)
}

func AccountFilter(ref bson.ObjectID) builder.Query {
	return Query().Filter(AccountField(), ref)
}

func StatusRefField() builder.Field {
	return Field("statusRef")
}

func StatusRefFilter(ref bson.ObjectID) builder.Query {
	return Query().Filter(StatusRefField(), ref)
}

func PriorityRefField() builder.Field {
	return Field("priorityRef")
}

func PriorityRefFilter(ref bson.ObjectID) builder.Query {
	return Query().Filter(PriorityRefField(), ref)
}

func IndexField() builder.Field {
	return Field("index")
}

func IndexFilter(index int) builder.Query {
	return Query().Filter(IndexField(), index)
}

func IndexOpFilter(index int, operation builder.MongoOperation) builder.Query {
	return Query().Comparison(IndexField(), operation, index)
}

func Patch() builder.Patch {
	return builderimp.NewPatchImp()
}

func Accumulator(operator builder.MongoOperation, value any) builder.Accumulator {
	return builderimp.NewAccumulator(operator, value)
}

func GroupAccumulator(field builder.Field, acc builder.Accumulator) builder.GroupAccumulator {
	return builderimp.NewGroupAccumulator(field, acc)
}

func Literal(value any) builder.Expression {
	return builderimp.NewLiteralExpression(value)
}

func Projection(alias builder.Alias) builder.Projection {
	return builderimp.NewAliasProjection(alias)
}

func IncludeField(field builder.Field) builder.Projection {
	return builderimp.IncludeField(field)
}

func ExcludeField(field builder.Field) builder.Projection {
	return builderimp.ExcludeField(field)
}

func ProjectionExpr(field builder.Field, expr builder.Expression) builder.Projection {
	return builderimp.NewProjectionExpr(field, expr)
}

func NullAlias(lhs builder.Field) builder.Alias {
	return builderimp.NewNullAlias(lhs)
}

func SimpleAlias(lhs, rhs builder.Field) builder.Alias {
	return builderimp.NewSimpleAlias(lhs, rhs)
}

func ComplexAlias(lhs builder.Field, rhs []builder.Alias) builder.Alias {
	return builderimp.NewComplexAlias(lhs, rhs)
}

func Aliases(aliases ...builder.Alias) builder.Alias {
	return builderimp.NewAliases(aliases...)
}

func AddToSet(value builder.Expression) builder.Expression {
	return builderimp.AddToSet(value)
}

func Size(value builder.Expression) builder.Expression {
	return builderimp.Size(value)
}

func InRef(value builder.Field) builder.Expression {
	return builderimp.InRef(value)
}

func In(values ...any) builder.Expression {
	return builderimp.In(values)
}

func Cond(condition builder.Expression, ifTrue, ifFalse any) builder.Expression {
	return builderimp.NewCond(condition, ifTrue, ifFalse)
}

func And(exprs ...builder.Expression) builder.Expression {
	return builderimp.NewAnd(exprs...)
}

func Or(exprs ...builder.Expression) builder.Expression {
	return builderimp.NewOr(exprs...)
}

func Type(expr builder.Expression) builder.Expression {
	return builderimp.NewType(expr)
}

func Not(expression builder.Expression) builder.Expression {
	return builderimp.NewNot(expression)
}

func Sum(expression builder.Expression) builder.Expression {
	return builderimp.NewSum(expression)
}

func Assign(field builder.Field, expression builder.Expression) builder.Projection {
	return builderimp.NewAssignment(field, expression)
}

func SetUnion(exprs ...builder.Expression) builder.Expression {
	return builderimp.NewSetUnion(exprs...)
}

func Eq(left, right builder.Expression) builder.Expression {
	return builderimp.Eq(left, right)
}

func Gt(left, right builder.Expression) builder.Expression {
	return builderimp.Gt(left, right)
}

func Lt(left, right builder.Expression) builder.Expression {
	return builderimp.NewLt(left, right)
}

func Array(expressions ...builder.Expression) builder.Array {
	return builderimp.NewArray(expressions...)
}

func IfNull(cond, replacement builder.Expression) builder.Expression {
	return builderimp.NewIfNull(cond, replacement)
}

func Each(exprs ...builder.Expression) builder.Expression {
	return builderimp.NewEach(exprs...)
}

func Push(expression builder.Expression) builder.Expression {
	return builderimp.NewPush(expression)
}

func Min(expression builder.Expression) builder.Expression {
	return builderimp.NewMin(expression)
}

func Ne(left, right builder.Expression) builder.Expression {
	return builderimp.Ne(left, right)
}

func Compute(field builder.Field, expression builder.Expression) builder.Expression {
	return builderimp.NewCompute(field, expression)
}

func First(expr builder.Expression) builder.Expression {
	return builderimp.First(expr)
}

func Value(value any) builder.Value {
	return builderimp.NewValue(value)
}

func Exists(field builder.Field, exists bool) builder.Query {
	return Query().Comparison(field, builder.Exists, exists)
}
