hako/internal/archival/domain/category_service.go

104 lines
3.2 KiB
Go

package domain
import (
"context"
"fmt"
archivalStore "git.nakama.town/fmartingr/hako/internal/archival/store"
"git.nakama.town/fmartingr/hako/internal/dependencies"
"git.nakama.town/fmartingr/hako/internal/model"
)
// CategoryDomain handles business logic for categories
type CategoryDomain struct {
deps model.Dependencies
}
// NewCategoryDomain creates a new CategoryDomain
func NewCategoryDomain(deps model.Dependencies) model.CategoryDomain {
return &CategoryDomain{deps: deps}
}
// getDeps returns the concrete dependencies implementation
func (d *CategoryDomain) getDeps() *dependencies.Dependencies {
return d.deps.(*dependencies.Dependencies)
}
// DetermineCategoriesFromMimeType returns slice of category IDs matching the MIME type
func (d *CategoryDomain) DetermineCategoriesFromMimeType(ctx context.Context, mimeType string) ([]string, error) {
deps := d.getDeps()
categories, err := deps.CategoryStore.GetByMimeType(ctx, mimeType)
if err != nil {
return nil, fmt.Errorf("failed to determine categories from MIME type: %w", err)
}
categoryIDs := make([]string, 0, len(categories))
for _, cat := range categories {
categoryIDs = append(categoryIDs, cat.ID)
}
return categoryIDs, nil
}
// UpdateLinkCategories analyzes MIME types and updates link's categories
func (d *CategoryDomain) UpdateLinkCategories(ctx context.Context, linkID string, mimeTypes []string) error {
deps := d.getDeps()
// Collect all unique category IDs from all MIME types
categoryIDSet := make(map[string]bool)
for _, mimeType := range mimeTypes {
if mimeType == "" {
continue
}
categoryIDs, err := d.DetermineCategoriesFromMimeType(ctx, mimeType)
if err != nil {
// Log error but continue with other MIME types
deps.Logger().Error("Failed to determine categories from MIME type", "mimeType", mimeType, "error", err)
continue
}
for _, catID := range categoryIDs {
categoryIDSet[catID] = true
}
}
// Get current categories for the link
currentCategories, err := deps.LinkCategoryStore.GetCategoriesByLinkID(ctx, linkID)
if err != nil {
return fmt.Errorf("failed to get current categories: %w", err)
}
currentCategoryIDSet := make(map[string]bool)
for _, cat := range currentCategories {
currentCategoryIDSet[cat.ID] = true
}
// Add new categories
for catID := range categoryIDSet {
if !currentCategoryIDSet[catID] {
if err := deps.LinkCategoryStore.AddCategory(ctx, linkID, catID); err != nil {
return fmt.Errorf("failed to add category to link: %w", err)
}
}
}
// Remove categories that are no longer applicable (only keep categories from the latest archive)
for catID := range currentCategoryIDSet {
if !categoryIDSet[catID] {
if err := deps.LinkCategoryStore.RemoveCategory(ctx, linkID, catID); err != nil {
return fmt.Errorf("failed to remove category from link: %w", err)
}
}
}
return nil
}
// ListCategories retrieves all categories
func (d *CategoryDomain) ListCategories(ctx context.Context) ([]*model.Category, error) {
deps := d.getDeps()
opts := archivalStore.CategoryListOptions{}
categories, err := deps.CategoryStore.List(ctx, opts)
if err != nil {
return nil, fmt.Errorf("failed to list categories: %w", err)
}
return categories, nil
}