package repository

import (
	"context"

	"gitlab.com/mbugroup/lti-api.git/internal/common/repository"
	entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
	"gorm.io/gorm"
)

type ProductionStandardRepository interface {
	repository.BaseRepository[entity.ProductionStandard]
	GetAll(ctx context.Context, offset, limit int, modifier func(*gorm.DB) *gorm.DB) ([]entity.ProductionStandard, int64, error)
	GetByID(ctx context.Context, id uint, modifier func(*gorm.DB) *gorm.DB) (*entity.ProductionStandard, error)
	NameExists(ctx context.Context, name string, excludeID *uint) (bool, error)
	IdExists(ctx context.Context, id uint) (bool, error)
	GetByProjectCategory(ctx context.Context, projectCategory string) ([]entity.ProductionStandard, error)
}

type ProductionStandardRepositoryImpl struct {
	*repository.BaseRepositoryImpl[entity.ProductionStandard]
	db *gorm.DB
}

func NewProductionStandardRepository(db *gorm.DB) ProductionStandardRepository {
	return &ProductionStandardRepositoryImpl{
		BaseRepositoryImpl: repository.NewBaseRepository[entity.ProductionStandard](db),
		db:                 db,
	}
}

func (r *ProductionStandardRepositoryImpl) GetAll(ctx context.Context, offset, limit int, modifier func(*gorm.DB) *gorm.DB) ([]entity.ProductionStandard, int64, error) {
	var standards []entity.ProductionStandard
	var total int64

	// Build base query
	q := r.db.WithContext(ctx).Model(&entity.ProductionStandard{})

	// Apply modifier for filters
	if modifier != nil {
		q = modifier(q)
	}

	// Count total
	if err := q.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// Re-apply modifier and add preloads for Find
	q = r.db.WithContext(ctx).Model(&entity.ProductionStandard{})
	if modifier != nil {
		q = modifier(q)
	}
	q = q.Preload("CreatedUser")

	// Find with offset and limit
	if err := q.Offset(offset).Limit(limit).Find(&standards).Error; err != nil {
		return nil, 0, err
	}

	return standards, total, nil
}

func (r *ProductionStandardRepositoryImpl) GetByID(ctx context.Context, id uint, modifier func(*gorm.DB) *gorm.DB) (*entity.ProductionStandard, error) {
	var standard entity.ProductionStandard

	q := r.db.WithContext(ctx).Model(&entity.ProductionStandard{})

	// Apply modifier
	if modifier != nil {
		q = modifier(q)
	}

	// Ensure CreatedUser is preloaded
	q = q.Preload("CreatedUser")

	if err := q.First(&standard, id).Error; err != nil {
		return nil, err
	}

	return &standard, nil
}

func (r *ProductionStandardRepositoryImpl) NameExists(ctx context.Context, name string, excludeID *uint) (bool, error) {
	return repository.ExistsByName[entity.ProductionStandard](ctx, r.db, name, excludeID)
}

func (r *ProductionStandardRepositoryImpl) IdExists(ctx context.Context, id uint) (bool, error) {
	return repository.Exists[entity.ProductionStandard](ctx, r.db, id)
}

func (r *ProductionStandardRepositoryImpl) GetByProjectCategory(ctx context.Context, projectCategory string) ([]entity.ProductionStandard, error) {
	var standards []entity.ProductionStandard
	err := r.db.WithContext(ctx).
		Preload("CreatedUser").
		Where("project_category = ?", projectCategory).
		Where("deleted_at IS NULL").
		Find(&standards).Error
	if err != nil {
		return nil, err
	}
	return standards, nil
}
