package replication

// Database access should be done through this file.
import (
	"github.com/pingcap/dbaas/central/db"
	"github.com/pingcap/dbaas/central/db/entity"
	"github.com/pingcap/errors"
	"gorm.io/gorm"
)

type ReplicationFilter struct {
	TenantID uint64
	CdcID    uint64
	Status   *entity.ReplicationStatus
	Statuss  []entity.ReplicationStatus
	Deleted  *bool
	Creating *bool
}

type ReplicationDao struct {
}

// fetches the entities of a QuerySet
func (d *ReplicationDao) FindReplication(filter ReplicationFilter) ([]entity.Replication, error) {
	var (
		err          error
		replications []entity.Replication
	)

	err = db.Transaction(func(tx *gorm.DB) error {
		tx = tx.Preload("Tenant").
			Preload("PrimaryCluster").
			Preload("SecondaryCluster").
			Preload("Backup").
			Preload("Task")

		if filter.TenantID != 0 {
			tx = tx.Where("replications.tenant_id = ?", filter.TenantID)
		}

		if filter.CdcID != 0 {
			tx = tx.Where("replications.cdc_task_id = ?", filter.CdcID)
		}

		if filter.Status != nil {
			tx = tx.Where("replications.replication_status = ?", *filter.Status)
		}

		if len(filter.Statuss) > 0 {
			tx = tx.Where("replications.replication_status IN (?)", filter.Statuss)
		}

		if filter.Deleted != nil {
			if *filter.Deleted {
				tx = tx.Where("replications.replication_status IN (?)", entity.ReplicationStatusDetached)
			} else {
				tx = tx.Where("replications.replication_status NOT IN (?)", entity.ReplicationStatusDetached)
			}
		}

		if filter.Creating != nil {
			if *filter.Creating {
				tx = tx.Where("replications.replication_status IN (?)", entity.ReplicationStatusCreating)
			} else {
				tx = tx.Where("replications.replication_status NOT IN (?)", entity.ReplicationStatusCreating)
			}
		}

		qs := entity.NewReplicationQuerySet(tx)

		err = qs.OrderDescByCreatedAt().All(&replications)
		if err != nil {
			return errors.AddStack(err)
		}

		return nil
	})
	if err != nil {
		return nil, err
	}

	return replications, nil
}

func (d *ReplicationDao) UpdateReplication(task entity.Replication, schemas []entity.ReplicationDBSchemaField) error {
	return db.Transaction(func(tx *gorm.DB) error {
		return task.Update(tx, schemas...)
	})
}
