package repository

import (
	"context"
	"errors"
	"fmt"

	"gorm.io/gorm"
)

// Exists reports whether a record with the given ID exists for type T.
func Exists[T any](ctx context.Context, db *gorm.DB, id uint) (bool, error) {
	var marker int
	err := db.WithContext(ctx).
		Model(new(T)).
		Select("1").
		Where("id = ?", id).
		Limit(1).
		Take(&marker).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return false, nil
	}
	if err != nil {
		return false, err
	}
	return true, nil
}

func ExistsByName[T any](ctx context.Context, db *gorm.DB, name string, excludeID *uint) (bool, error) {
	q := db.WithContext(ctx).
		Model(new(T)).
		Select("1").
		Where("name = ?", name).
		Where("deleted_at IS NULL")
	if excludeID != nil {
		q = q.Where("id <> ?", *excludeID)
	}
	var marker int
	if err := q.Limit(1).Take(&marker).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return false, nil
		}
		return false, err
	}
	return true, nil
}

func ExistsByField[T any](ctx context.Context, db *gorm.DB, field string, value any, excludeID *uint) (bool, error) {
	if field == "" {
		return false, fmt.Errorf("field is required")
	}
	q := db.WithContext(ctx).
		Model(new(T)).
		Select("1").
		Where(fmt.Sprintf("%s = ?", field), value).
		Where("deleted_at IS NULL")
	if excludeID != nil {
		q = q.Where("id <> ?", *excludeID)
	}
	var marker int
	if err := q.Limit(1).Take(&marker).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return false, nil
		}
		return false, err
	}
	return true, nil
}
