package service import ( "bugulma/backend/internal/domain" "bugulma/backend/internal/localization" "fmt" "gorm.io/gorm" ) // EntityLoaderService provides generic entity loading functionality using the registry type EntityLoaderService struct { db *gorm.DB } // NewEntityLoaderService creates a new entity loader service func NewEntityLoaderService(db *gorm.DB) *EntityLoaderService { return &EntityLoaderService{db: db} } // LoadEntities loads all entities of a specific type using the registry handlers func (s *EntityLoaderService) LoadEntities(entityType string, options localization.LoadOptions) ([]interface{}, error) { desc, exists := localization.GetEntityDescriptor(entityType) if !exists { return nil, fmt.Errorf("unsupported entity type: %s", entityType) } // Use type-specific loading with proper type casting switch entityType { case "heritage_title": handler := desc.Handler.(domain.EntityHandler[*domain.HeritageTitle]) entities, err := handler.LoadEntities(s.db, domain.EntityLoadOptions{IncludeAllSites: options.IncludeAllSites}) if err != nil { return nil, err } result := make([]interface{}, len(entities)) for i, e := range entities { result[i] = e } return result, nil case "timeline_item": handler := desc.Handler.(domain.EntityHandler[*domain.TimelineItem]) entities, err := handler.LoadEntities(s.db, domain.EntityLoadOptions{IncludeAllSites: options.IncludeAllSites}) if err != nil { return nil, err } result := make([]interface{}, len(entities)) for i, e := range entities { result[i] = e } return result, nil case "heritage_source": handler := desc.Handler.(domain.EntityHandler[*domain.HeritageSource]) entities, err := handler.LoadEntities(s.db, domain.EntityLoadOptions{IncludeAllSites: options.IncludeAllSites}) if err != nil { return nil, err } result := make([]interface{}, len(entities)) for i, e := range entities { result[i] = e } return result, nil case "site": handler := desc.Handler.(domain.EntityHandler[*domain.Site]) entities, err := handler.LoadEntities(s.db, domain.EntityLoadOptions{IncludeAllSites: options.IncludeAllSites}) if err != nil { return nil, err } result := make([]interface{}, len(entities)) for i, e := range entities { result[i] = e } return result, nil case "organization": handler := desc.Handler.(domain.EntityHandler[*domain.Organization]) entities, err := handler.LoadEntities(s.db, domain.EntityLoadOptions{IncludeAllSites: options.IncludeAllSites}) if err != nil { return nil, err } result := make([]interface{}, len(entities)) for i, e := range entities { result[i] = e } return result, nil case "geographical_feature": handler := desc.Handler.(domain.EntityHandler[*domain.GeographicalFeature]) entities, err := handler.LoadEntities(s.db, domain.EntityLoadOptions{IncludeAllSites: options.IncludeAllSites}) if err != nil { return nil, err } result := make([]interface{}, len(entities)) for i, e := range entities { result[i] = e } return result, nil case "product": handler := desc.Handler.(domain.EntityHandler[*domain.Product]) entities, err := handler.LoadEntities(s.db, domain.EntityLoadOptions{IncludeAllSites: options.IncludeAllSites}) if err != nil { return nil, err } result := make([]interface{}, len(entities)) for i, e := range entities { result[i] = e } return result, nil default: return nil, fmt.Errorf("unsupported entity type: %s", entityType) } } // LoadEntityByID loads a single entity by ID using the registry func (s *EntityLoaderService) LoadEntityByID(entityType, entityID string) (interface{}, error) { desc, exists := localization.GetEntityDescriptor(entityType) if !exists { return nil, fmt.Errorf("unsupported entity type: %s", entityType) } // Use type-specific loading with proper type casting switch entityType { case "heritage_title": handler := desc.Handler.(domain.EntityHandler[*domain.HeritageTitle]) entities, err := handler.LoadEntities(s.db, domain.EntityLoadOptions{}) if err != nil { return nil, err } for _, e := range entities { if handler.GetEntityID(e) == entityID { return e, nil } } return nil, fmt.Errorf("entity not found: %s", entityID) case "timeline_item": handler := desc.Handler.(domain.EntityHandler[*domain.TimelineItem]) entities, err := handler.LoadEntities(s.db, domain.EntityLoadOptions{}) if err != nil { return nil, err } for _, e := range entities { if handler.GetEntityID(e) == entityID { return e, nil } } return nil, fmt.Errorf("entity not found: %s", entityID) case "heritage_source": handler := desc.Handler.(domain.EntityHandler[*domain.HeritageSource]) entities, err := handler.LoadEntities(s.db, domain.EntityLoadOptions{}) if err != nil { return nil, err } for _, e := range entities { if handler.GetEntityID(e) == entityID { return e, nil } } return nil, fmt.Errorf("entity not found: %s", entityID) case "site": handler := desc.Handler.(domain.EntityHandler[*domain.Site]) entities, err := handler.LoadEntities(s.db, domain.EntityLoadOptions{IncludeAllSites: true}) if err != nil { return nil, err } for _, e := range entities { if handler.GetEntityID(e) == entityID { return e, nil } } return nil, fmt.Errorf("entity not found: %s", entityID) case "organization": handler := desc.Handler.(domain.EntityHandler[*domain.Organization]) entities, err := handler.LoadEntities(s.db, domain.EntityLoadOptions{}) if err != nil { return nil, err } for _, e := range entities { if handler.GetEntityID(e) == entityID { return e, nil } } return nil, fmt.Errorf("entity not found: %s", entityID) case "geographical_feature": handler := desc.Handler.(domain.EntityHandler[*domain.GeographicalFeature]) entities, err := handler.LoadEntities(s.db, domain.EntityLoadOptions{}) if err != nil { return nil, err } for _, e := range entities { if handler.GetEntityID(e) == entityID { return e, nil } } return nil, fmt.Errorf("entity not found: %s", entityID) case "product": handler := desc.Handler.(domain.EntityHandler[*domain.Product]) entities, err := handler.LoadEntities(s.db, domain.EntityLoadOptions{}) if err != nil { return nil, err } for _, e := range entities { if handler.GetEntityID(e) == entityID { return e, nil } } return nil, fmt.Errorf("entity not found: %s", entityID) default: return nil, fmt.Errorf("unsupported entity type: %s", entityType) } } // GetEntityID returns the ID of an entity using the registry handler func (s *EntityLoaderService) GetEntityID(entity interface{}) string { // Determine entity type from the entity itself var entityType string switch entity.(type) { case *domain.HeritageTitle: entityType = "heritage_title" case *domain.TimelineItem: entityType = "timeline_item" case *domain.HeritageSource: entityType = "heritage_source" case *domain.Site: entityType = "site" case *domain.Organization: entityType = "organization" case *domain.GeographicalFeature: entityType = "geographical_feature" case *domain.Product: entityType = "product" default: return "" } desc, exists := localization.GetEntityDescriptor(entityType) if !exists { return "" } // Use type-specific handler to get ID switch e := entity.(type) { case *domain.HeritageTitle: handler := desc.Handler.(domain.EntityHandler[*domain.HeritageTitle]) return handler.GetEntityID(e) case *domain.TimelineItem: handler := desc.Handler.(domain.EntityHandler[*domain.TimelineItem]) return handler.GetEntityID(e) case *domain.HeritageSource: handler := desc.Handler.(domain.EntityHandler[*domain.HeritageSource]) return handler.GetEntityID(e) case *domain.Site: handler := desc.Handler.(domain.EntityHandler[*domain.Site]) return handler.GetEntityID(e) case *domain.Organization: handler := desc.Handler.(domain.EntityHandler[*domain.Organization]) return handler.GetEntityID(e) case *domain.GeographicalFeature: handler := desc.Handler.(domain.EntityHandler[*domain.GeographicalFeature]) return handler.GetEntityID(e) case *domain.Product: handler := desc.Handler.(domain.EntityHandler[*domain.Product]) return handler.GetEntityID(e) } return "" } // GetRussianContent returns the Russian content for an entity field using the registry handler func (s *EntityLoaderService) GetRussianContent(entity interface{}, field string) string { // Determine entity type from the entity itself var entityType string switch entity.(type) { case *domain.HeritageTitle: entityType = "heritage_title" case *domain.TimelineItem: entityType = "timeline_item" case *domain.HeritageSource: entityType = "heritage_source" case *domain.Site: entityType = "site" case *domain.Organization: entityType = "organization" case *domain.GeographicalFeature: entityType = "geographical_feature" case *domain.Product: entityType = "product" default: return "" } desc, exists := localization.GetEntityDescriptor(entityType) if !exists { return "" } // Use type-specific handler to get field value switch e := entity.(type) { case *domain.HeritageTitle: handler := desc.Handler.(domain.EntityHandler[*domain.HeritageTitle]) return handler.GetFieldValue(e, field) case *domain.TimelineItem: handler := desc.Handler.(domain.EntityHandler[*domain.TimelineItem]) return handler.GetFieldValue(e, field) case *domain.HeritageSource: handler := desc.Handler.(domain.EntityHandler[*domain.HeritageSource]) return handler.GetFieldValue(e, field) case *domain.Site: handler := desc.Handler.(domain.EntityHandler[*domain.Site]) return handler.GetFieldValue(e, field) case *domain.Organization: handler := desc.Handler.(domain.EntityHandler[*domain.Organization]) return handler.GetFieldValue(e, field) case *domain.GeographicalFeature: handler := desc.Handler.(domain.EntityHandler[*domain.GeographicalFeature]) return handler.GetFieldValue(e, field) case *domain.Product: handler := desc.Handler.(domain.EntityHandler[*domain.Product]) return handler.GetFieldValue(e, field) } return "" }