package dbutil

import (
	"errors"
	"fmt"

	"github.com/pingcap/dbaas/central/db/entity"
	"github.com/pingcap/errcode"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

// PreloadCluster preloads the dependencies of entity.Cluster
func PreloadCluster(tx *gorm.DB) *gorm.DB {
	// see limitation, we can not use go-queryset
	// https://github.com/jirfag/go-queryset/issues/33
	return tx.Preload("ComponentsV2").
		Preload("ComponentsV2.Region").
		Preload("ComponentsV2.InternalProfile").
		Preload("ComponentsV2.InternalProfile.InfraCompute").
		Preload("Connections").
		Preload("Provider").
		Preload("CreatedBy").
		Preload("Tenant").
		Preload("Project").
		Preload("CrossAccountDeployment")
}

// TagNotFound wraps the `gorm.ErrRecordNotFound` to a new error type.
func TagNotFound(err error) error {
	if err == gorm.ErrRecordNotFound {
		return errcode.NewNotFoundErr(err)
	}
	return err
}

type Result struct {
	ComponentName string
	Total         uint32
}

func GetActiveClusterCount(tx *gorm.DB, tenantID entity.ID) (int64, error) {
	var count int64
	return count, tx.Clauses(clause.Locking{Strength: "UPDATE"}).Table("clusters").Where(" clusters.tenant_id=? and clusters.status not in (?) ", tenantID, entity.DeletedOrClearedClusterStatus).Count(&count).Error
}

func GenerateAutoBackupName(clusterID entity.ID) string {
	return fmt.Sprintf("ab-%d", clusterID)
}

func CheckResourceOrgIDAndProjectID(orgID, resourceOrgID, projectID, resourceProjectID entity.ID) error {
	if orgID != resourceOrgID || projectID != resourceProjectID {
		return errcode.NewForbiddenErr(errors.New("you do not have permission to access this resource"))
	}
	return nil
}

func UserInProject(userProjects []entity.Project, projectID entity.ID) bool {
	userInProject := false
	for _, project := range userProjects {
		if project.ID == projectID {
			userInProject = true
		}
	}
	return userInProject
}

func CheckProjectID(userProjects []entity.Project, projectID entity.ID) error {
	userInProject := UserInProject(userProjects, projectID)
	if userInProject {
		return nil
	}

	return errcode.NewForbiddenErr(errors.New("you do not have permission to access this project"))
}
