package repo

import (
	"context"
	"fmt"

	"gorm.io/gorm/clause"

	"github.com/pingcap-inc/clinic_cloud_server/pkg/db"
)

type AlertSubscriberRepo struct{}

func (repo *AlertSubscriberRepo) Load(ctx context.Context, id uint) (*db.AlertSubscriber, error) {
	item := &db.AlertSubscriber{}
	err := db.GetDB().Model(&db.AlertSubscriber{}).Where("id = ?", id).First(item).Error
	if err != nil {
		return nil, fmt.Errorf("load alert subscribers %d failed: %w", id, err)
	}
	return item, nil
}

func (repo *AlertSubscriberRepo) Count(ctx context.Context,
	tenantId, projectId uint64,
) (int64, error) {
	var count int64
	err := db.GetDB().Model(&db.AlertSubscriber{}).
		Where("tenant_id = ? AND project_id = ? AND deleted_at IS NULL", tenantId, projectId).
		Count(&count).Error
	if err != nil {
		return 0, fmt.Errorf("count alert subscribers failed: %w", err)
	}
	return count, nil
}

type AlertSubscriberQuery struct {
	UserId         uint64
	Name           string
	SubscriberType string
}

func (repo *AlertSubscriberRepo) Query(ctx context.Context,
	tenantId, targetId uint64,
	clusterType string,
	query AlertSubscriberQuery,
) ([]*db.AlertSubscriber, error) {
	rdb := db.GetDB().Model(&db.AlertSubscriber{})
	if clusterType == "NEXT-GEN" {
		rdb = rdb.Where("tenant_id = ? AND cluster_id = ?", tenantId, targetId)
	} else {
		rdb = rdb.Where("tenant_id = ? AND project_id = ?", tenantId, targetId)
	}
	if query.UserId != 0 {
		rdb = rdb.Where("user_id = ?", query.UserId)
	}
	if query.Name != "" {
		rdb = rdb.Where("name = ?", query.Name)
	}
	if query.SubscriberType != "" {
		rdb = rdb.Where("subscriber_type = ?", query.SubscriberType)
	}
	rdb = rdb.Where("deleted_at IS NULL")

	items := make([]*db.AlertSubscriber, 0)
	err := rdb.Find(&items).Error
	if err != nil {
		return nil, fmt.Errorf("query alert subscribers failed: %w", err)
	}
	return items, nil
}

func (repo *AlertSubscriberRepo) Save(ctx context.Context, item *db.AlertSubscriber) error {
	err := db.GetDB().Save(item).Error
	if err != nil {
		return fmt.Errorf("save alert subscriber %d failed: %w", item.ID, err)
	}
	return nil
}

func (repo *AlertSubscriberRepo) BatchSave(ctx context.Context, items []*db.AlertSubscriber) error {
	if len(items) == 0 {
		return nil
	}
	wdb := db.GetDB().Model(&db.AlertSubscriber{})
	err := wdb.Clauses(clause.OnConflict{
		UpdateAll: true,
	}).Create(items).Error
	if err != nil {
		return fmt.Errorf("batch save alert subscribers failed: %w", err)
	}
	return nil
}

func (repo *AlertSubscriberRepo) Delete(ctx context.Context, item *db.AlertSubscriber) error {
	if item == nil || item.ID == 0 {
		return nil
	}
	err := db.GetDB().Delete(item).Error
	if err != nil {
		return fmt.Errorf("delete alert subscriber %d failed: %w", item.ID, err)
	}
	return nil
}

func (repo *AlertSubscriberRepo) BatchDelete(ctx context.Context, items []*db.AlertSubscriber) error {
	if len(items) == 0 {
		return nil
	}
	err := db.GetDB().Delete(items).Error
	if err != nil {
		return fmt.Errorf("batch delete alert subscribers failed: %w", err)
	}
	return nil
}
