package repository import ( "context" "strings" "time" "bugulma/backend/internal/domain" "gorm.io/gorm" ) // StaticPageRepository implements domain.StaticPageRepository with GORM type StaticPageRepository struct { *BaseRepository[domain.StaticPage] db *gorm.DB } // NewStaticPageRepository creates a new GORM-based static page repository func NewStaticPageRepository(db *gorm.DB) domain.StaticPageRepository { return &StaticPageRepository{ BaseRepository: NewBaseRepository[domain.StaticPage](db), db: db, } } // GetBySlug retrieves a page by slug func (r *StaticPageRepository) GetBySlug(ctx context.Context, slug string) (*domain.StaticPage, error) { return r.FindOneWhereWithContext(ctx, "slug = ?", slug) } // Search searches pages by title and content func (r *StaticPageRepository) Search(ctx context.Context, query string) ([]*domain.StaticPage, error) { searchTerm := "%" + strings.ToLower(query) + "%" return r.FindWhereWithContext(ctx, "LOWER(title) LIKE ? OR LOWER(content) LIKE ?", searchTerm, searchTerm) } // AnnouncementRepository implements domain.AnnouncementRepository with GORM type AnnouncementRepository struct { *BaseRepository[domain.Announcement] db *gorm.DB } // NewAnnouncementRepository creates a new GORM-based announcement repository func NewAnnouncementRepository(db *gorm.DB) domain.AnnouncementRepository { return &AnnouncementRepository{ BaseRepository: NewBaseRepository[domain.Announcement](db), db: db, } } // GetAll retrieves announcements with filters func (r *AnnouncementRepository) GetAll(ctx context.Context, filters domain.AnnouncementFilters) ([]*domain.Announcement, error) { query := r.db.WithContext(ctx).Model(&domain.Announcement{}) if filters.IsActive != nil { query = query.Where("is_active = ?", *filters.IsActive) } if filters.Priority != nil { query = query.Where("priority = ?", *filters.Priority) } if filters.StartDate != nil { query = query.Where("start_date >= ?", *filters.StartDate) } if filters.EndDate != nil { query = query.Where("end_date <= ?", *filters.EndDate) } var announcements []*domain.Announcement result := query.Order("created_at DESC").Find(&announcements) if result.Error != nil { return nil, result.Error } return announcements, nil } // GetActive retrieves active announcements func (r *AnnouncementRepository) GetActive(ctx context.Context) ([]*domain.Announcement, error) { now := time.Now() return r.FindWhereWithContext(ctx, "is_active = ? AND (start_date IS NULL OR start_date <= ?) AND (end_date IS NULL OR end_date >= ?)", true, now, now) } // RecordView records a view for an announcement func (r *AnnouncementRepository) RecordView(ctx context.Context, id string) error { result := r.db.WithContext(ctx). Model(&domain.Announcement{}). Where("id = ?", id). UpdateColumn("views", gorm.Expr("views + 1")) return result.Error } // RecordClick records a click for an announcement func (r *AnnouncementRepository) RecordClick(ctx context.Context, id string) error { result := r.db.WithContext(ctx). Model(&domain.Announcement{}). Where("id = ?", id). UpdateColumn("clicks", gorm.Expr("clicks + 1")) return result.Error } // RecordDismissal records a dismissal for an announcement func (r *AnnouncementRepository) RecordDismissal(ctx context.Context, id string) error { result := r.db.WithContext(ctx). Model(&domain.Announcement{}). Where("id = ?", id). UpdateColumn("dismissals", gorm.Expr("dismissals + 1")) return result.Error } // MediaAssetRepository implements domain.MediaAssetRepository with GORM type MediaAssetRepository struct { *BaseRepository[domain.MediaAsset] db *gorm.DB } // NewMediaAssetRepository creates a new GORM-based media asset repository func NewMediaAssetRepository(db *gorm.DB) domain.MediaAssetRepository { return &MediaAssetRepository{ BaseRepository: NewBaseRepository[domain.MediaAsset](db), db: db, } } // GetAll retrieves media assets with filters func (r *MediaAssetRepository) GetAll(ctx context.Context, filters domain.MediaAssetFilters) ([]*domain.MediaAsset, error) { query := r.db.WithContext(ctx).Model(&domain.MediaAsset{}) if filters.Type != nil { query = query.Where("type = ?", *filters.Type) } if len(filters.Tags) > 0 { // Search for assets containing any of the tags for _, tag := range filters.Tags { query = query.Where("tags::text LIKE ?", "%"+tag+"%") } } var assets []*domain.MediaAsset result := query.Order("created_at DESC").Find(&assets) if result.Error != nil { return nil, result.Error } return assets, nil } // Search searches media assets by filename and tags func (r *MediaAssetRepository) Search(ctx context.Context, query string) ([]*domain.MediaAsset, error) { searchTerm := "%" + strings.ToLower(query) + "%" return r.FindWhereWithContext(ctx, "LOWER(filename) LIKE ? OR LOWER(original_name) LIKE ? OR tags::text LIKE ?", searchTerm, searchTerm, searchTerm) }