package service import ( "context" "fmt" "log" "bugulma/backend/internal/domain" "bugulma/backend/internal/matching" ) // IncrementalMatchCalculator handles incremental match recalculations type IncrementalMatchCalculator struct { matchingService *matching.Service matchRepo domain.MatchRepository economicService *EconomicService } // RecalculateMatch performs incremental recalculation for a single match func (imc *IncrementalMatchCalculator) RecalculateMatch(ctx context.Context, matchID string) error { match, err := imc.matchRepo.GetByID(ctx, matchID) if err != nil { return fmt.Errorf("failed to get match: %w", err) } // Get current resource flows sourceFlow, err := imc.matchingService.GetResourceFlowByID(ctx, match.SourceResourceID) if err != nil { return fmt.Errorf("failed to get source flow: %w", err) } targetFlow, err := imc.matchingService.GetResourceFlowByID(ctx, match.TargetResourceID) if err != nil { return fmt.Errorf("failed to get target flow: %w", err) } // Calculate distance sourceSite, err := imc.matchingService.GetSiteByID(ctx, sourceFlow.SiteID) if err != nil { return fmt.Errorf("failed to get source site: %w", err) } targetSite, err := imc.matchingService.GetSiteByID(ctx, targetFlow.SiteID) if err != nil { return fmt.Errorf("failed to get target site: %w", err) } distance := imc.matchingService.CalculateDistance( sourceSite.Latitude, sourceSite.Longitude, targetSite.Latitude, targetSite.Longitude, ) // Update distance in match match.DistanceKm = distance // Recalculate economic analysis using economic service if imc.economicService == nil { return fmt.Errorf("economic service is required for match recalculation") } economicAnalysis, err := imc.economicService.AnalyzeMatch(ctx, sourceFlow, targetFlow, distance) if err != nil { return fmt.Errorf("failed to recalculate economic analysis: %w", err) } // Update economic value in match match.EconomicValue = economicAnalysis.AnnualSavings // Recalculate compatibility and other scores // This would involve running the scoring algorithms again // For now, we update the match with recalculated economic data return imc.matchRepo.Update(ctx, match) } // RecalculateAffectedMatches recalculates multiple affected matches func (imc *IncrementalMatchCalculator) RecalculateAffectedMatches(ctx context.Context, matchIDs []string) error { for _, matchID := range matchIDs { if err := imc.RecalculateMatch(ctx, matchID); err != nil { log.Printf("Failed to recalculate match %s: %v", matchID, err) // Continue with other matches even if one fails } } return nil } // NewIncrementalMatchCalculator creates a new incremental match calculator func NewIncrementalMatchCalculator( matchingService *matching.Service, matchRepo domain.MatchRepository, economicService *EconomicService, ) *IncrementalMatchCalculator { return &IncrementalMatchCalculator{ matchingService: matchingService, matchRepo: matchRepo, economicService: economicService, } }