package service import ( "bugulma/backend/internal/domain" "bugulma/backend/internal/repository" "context" "fmt" "time" ) // TrustService provides trust metrics and data quality services type TrustService struct { trustRepo domain.TrustMetricsRepository verifiedRepo *repository.VerifiedDataRepository historicalRepo *repository.HistoricalSuccessRepository } // GetTrustRepository returns the trust metrics repository (for internal use) func (s *TrustService) GetTrustRepository() domain.TrustMetricsRepository { return s.trustRepo } // NewTrustService creates a new trust service func NewTrustService( trustRepo domain.TrustMetricsRepository, verifiedRepo *repository.VerifiedDataRepository, historicalRepo *repository.HistoricalSuccessRepository, ) *TrustService { return &TrustService{ trustRepo: trustRepo, verifiedRepo: verifiedRepo, historicalRepo: historicalRepo, } } // AssessDataQuality performs comprehensive data quality assessment for an organization func (s *TrustService) AssessDataQuality(ctx context.Context, orgID string) (*domain.DataQualityProfile, error) { profile, err := s.trustRepo.GetLatestProfile(ctx, orgID) if err != nil { return nil, fmt.Errorf("failed to get quality profile: %w", err) } // Enhance profile with additional calculations profile.Timeliness = s.calculateTimelinessScore(profile) profile.Consistency = s.calculateConsistencyScore(profile) // Recalculate overall score with all components profile.OverallScore = (profile.Completeness*0.3 + profile.Accuracy*0.3 + profile.Timeliness*0.2 + profile.Consistency*0.2) return profile, nil } // CalculateTrustScore calculates comprehensive trust score for an organization func (s *TrustService) CalculateTrustScore(ctx context.Context, orgID string) (*domain.TrustScore, error) { return s.historicalRepo.CalculateTrustScore(ctx, orgID) } // UpdateTrustMetrics updates trust metrics for an organization func (s *TrustService) UpdateTrustMetrics(ctx context.Context, orgID string, metrics []*domain.TrustMetrics) error { for _, metric := range metrics { metric.OrganizationID = orgID metric.LastUpdated = time.Now() // Calculate score based on value metric.Score = s.calculateScoreCategory(metric.Value) if err := s.trustRepo.Create(ctx, metric); err != nil { return fmt.Errorf("failed to create trust metric: %w", err) } } return nil } // SubmitForVerification submits data for verification func (s *TrustService) SubmitForVerification(ctx context.Context, verifiedData *domain.VerifiedData) error { verifiedData.Status = domain.VerificationPending return s.verifiedRepo.Create(ctx, verifiedData) } // VerifyData marks data as verified func (s *TrustService) VerifyData(ctx context.Context, dataID string, verifiedBy string, notes string) error { // Get existing verified data existing, err := s.verifiedRepo.GetByID(ctx, dataID) if err != nil { return fmt.Errorf("failed to get verified data: %w", err) } // Update verification status now := time.Now() existing.Status = domain.VerificationVerified existing.VerifiedBy = verifiedBy existing.VerifiedAt = &now existing.Notes = notes existing.ExpiresAt = &time.Time{} // Set expiration if needed return s.verifiedRepo.Update(ctx, existing) } // RecordHistoricalSuccess records historical success metrics func (s *TrustService) RecordHistoricalSuccess(ctx context.Context, success *domain.HistoricalSuccess) error { success.RecordedAt = time.Now() return s.historicalRepo.Create(ctx, success) } // GetTrustDashboard returns trust dashboard data for an organization func (s *TrustService) GetTrustDashboard(ctx context.Context, orgID string) (*TrustDashboard, error) { // Get trust score trustScore, err := s.CalculateTrustScore(ctx, orgID) if err != nil { return nil, fmt.Errorf("failed to calculate trust score: %w", err) } // Get quality profile qualityProfile, err := s.AssessDataQuality(ctx, orgID) if err != nil { return nil, fmt.Errorf("failed to assess data quality: %w", err) } // Get recent historical metrics historical, err := s.historicalRepo.GetByOrganization(ctx, orgID) if err != nil { return nil, fmt.Errorf("failed to get historical metrics: %w", err) } // Get verification status verifiedData, err := s.verifiedRepo.GetByOrganization(ctx, orgID) if err != nil { return nil, fmt.Errorf("failed to get verified data: %w", err) } dashboard := &TrustDashboard{ OrganizationID: orgID, TrustScore: trustScore, QualityProfile: qualityProfile, HistoricalMetrics: historical, VerifiedData: verifiedData, LastUpdated: time.Now(), } return dashboard, nil } // calculateTimelinessScore calculates how timely the data is func (s *TrustService) calculateTimelinessScore(profile *domain.DataQualityProfile) float64 { // Check how recent the metrics are daysSinceAssessment := time.Since(profile.LastAssessed).Hours() / 24 // Score decreases with age if daysSinceAssessment < 30 { return 0.9 } else if daysSinceAssessment < 90 { return 0.7 } else if daysSinceAssessment < 180 { return 0.5 } else { return 0.3 } } // calculateConsistencyScore calculates data consistency func (s *TrustService) calculateConsistencyScore(profile *domain.DataQualityProfile) float64 { // Check for conflicting or inconsistent metrics // This is a simplified implementation if len(profile.Metrics) < 3 { return 0.5 // Not enough data to assess consistency } // Look for metrics with similar names but different values metricGroups := make(map[string][]float64) for _, metric := range profile.Metrics { metricGroups[metric.MetricName] = append(metricGroups[metric.MetricName], metric.Value) } // Check variance within groups consistentGroups := 0 totalGroups := len(metricGroups) for _, values := range metricGroups { if len(values) > 1 { // Calculate simple variance avg := 0.0 for _, v := range values { avg += v } avg /= float64(len(values)) variance := 0.0 for _, v := range values { diff := v - avg variance += diff * diff } variance /= float64(len(values)) // Low variance indicates consistency if variance < 0.1 { // Threshold for consistency consistentGroups++ } } else { consistentGroups++ // Single value is consistent by definition } } if totalGroups == 0 { return 0.5 } return float64(consistentGroups) / float64(totalGroups) } // calculateScoreCategory converts numeric score to category func (s *TrustService) calculateScoreCategory(value float64) string { switch { case value >= 0.9: return "excellent" case value >= 0.8: return "good" case value >= 0.6: return "fair" default: return "poor" } } // TrustDashboard represents comprehensive trust dashboard data type TrustDashboard struct { OrganizationID string `json:"organization_id"` TrustScore *domain.TrustScore `json:"trust_score"` QualityProfile *domain.DataQualityProfile `json:"quality_profile"` HistoricalMetrics []*domain.HistoricalSuccess `json:"historical_metrics"` VerifiedData []*domain.VerifiedData `json:"verified_data"` LastUpdated time.Time `json:"last_updated"` }