package project

import (
	"context"

	"github.com/pingcap/errors"
	"github.com/tidbcloud/account/internel/dao/entity"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

type ProjectFilter struct {
	TenantIDs  []entity.ID
	ProjectIDs []entity.ID
}

func FindProjects(tx *gorm.DB, filter *ProjectFilter) (map[entity.ID]*entity.Project, error) {
	if filter.TenantIDs != nil {
		tx = tx.Where("tenant_id in (?)", filter.TenantIDs)
	}

	if filter.ProjectIDs != nil {
		tx = tx.Where("id in (?)", filter.ProjectIDs)
	}

	var projs []*entity.Project
	if err := tx.Find(&projs).Error; err != nil {
		return nil, errors.AddStack(err)
	}
	outs := make(map[entity.ID]*entity.Project, len(projs))
	for _, each := range projs {
		outs[each.ID] = each
	}
	return outs, nil
}

func GetProject(ctx context.Context, tx *gorm.DB, projectID entity.ID) (*entity.Project, error) {
	proj := &entity.Project{}
	if err := tx.Model(&entity.Project{}).Where("id=?", projectID).First(proj).Error; err != nil {
		return nil, err
	}
	return proj, nil
}

func GetActiveProjectByOrgID(tx *gorm.DB, tenantID entity.ID) (entity.Project, error) {
	var project entity.Project

	err := entity.NewProjectQuerySet(tx).TenantIDEq(tenantID).StatusEq(entity.ProjectStatusActive).OrderAscByID().One(&project)

	return project, err
}

//func DeleteProject(ctx context.Context, tx *gorm.DB, orgID, projectID entity.ID) error {
//	tilog.WithContextL(ctx).Info("delete project", zap.Uint64("projectID", projectID.Uint64()))
//	now := time.Now()
//	err := entity.NewProjectQuerySet(tx).TenantIDEq(orgID).IDEq(projectID).StatusEq(entity.ProjectStatusActive).GetUpdater().
//		SetDeletedTime(&now).SetStatus(entity.ProjectStatusDeleted).Update()
//	if err != nil {
//		return errors.Annotate(err, "failed to update project status")
//	}
//	return nil
//}

func ClearProject(ctx context.Context, tx *gorm.DB, projectID entity.ID) error {
	tilog.WithContextL(ctx).Info("clear project", zap.Uint64("projectID", projectID.Uint64()))
	err := entity.NewProjectQuerySet(tx).IDEq(projectID).StatusEq(entity.ProjectStatusDeleted).GetUpdater().
		SetStatus(entity.ProjectStatusCleared).Update()
	if err != nil {
		return errors.Annotatef(err, "failed to update status of project %d to cleared", projectID)
	}
	return nil
}

func GetActiveProjects(ctx context.Context, tx *gorm.DB, orgID entity.ID) ([]entity.Project, error) {
	var projects []entity.Project
	err := entity.NewProjectQuerySet(tx).TenantIDEq(orgID).StatusEq(entity.ProjectStatusActive).OrderDescByCreatedAt().All(&projects)
	if err != nil {
		tilog.WithContextL(ctx).Error("failed to query active projects", zap.Uint64("tenantID", orgID.Uint64()))
		return nil, errors.Annotatef(err, "failed to query active projects of org %d", orgID.Uint64())
	}
	tilog.Info(ctx, "GetActiveProjects", zap.Any("size", len(projects)))
	return projects, nil
}
