lowConfidenceThreshold = max(0.0, min(1.0, $lowConfidenceThreshold)); } public function analyze(IntegrationResult $result): PreviewAnalysis { if (! $result->isEnabled()) { return new PreviewAnalysis($result); } $productScore = $result->getProductScore(); $confidence = $result->getConfidenceReport(); $quality = $result->getQualityReport(); $qualitySummary = $quality !== null ? new PreviewQualitySummary( $quality->getOverallGrade(), $quality->getOverallScore(), $quality->getStrengths(), $quality->getWeaknesses(), $quality->getMissingInformation() ) : null; return new PreviewAnalysis( $result, $productScore !== null ? $productScore->getConfidenceScore() : null, $confidence !== null ? $confidence->getOverallScore() : null, $qualitySummary, $this->mergeSummary($productScore), $this->recommendations($result) ); } public function getAiSuggestions(IntegrationResult $result): array { return []; } public function getSeoSuggestions(IntegrationResult $result): array { return []; } public function getMetadataSuggestions(IntegrationResult $result): array { return []; } private function mergeSummary(?ProductScore $productScore): array { if ($productScore === null || $productScore->getMergeTrace() === null) { return []; } $summary = []; foreach ($productScore->getMergeTrace()->getDecisions() as $field => $decision) { if (! $decision instanceof MergeDecision) { continue; } $summary[$field] = [ 'selected_provider' => $decision->getSelectedProvider(), 'rejected_providers' => $decision->getRejectedProviders(), 'reason' => $decision->getReason(), 'score' => $decision->getScore(), 'timestamp' => $decision->getTimestamp(), ]; } return $summary; } private function recommendations(IntegrationResult $result): array { $recommendations = []; $productScore = $result->getProductScore(); $confidence = $result->getConfidenceReport(); $quality = $result->getQualityReport(); if ($this->isMissing($productScore, 'description')) { $recommendations[] = new PreviewRecommendation( 'missing_description', 'Descrizione mancante', PreviewRecommendation::TYPE_DATA, 'description', 'high' ); } if ($quality !== null && in_array('image_quality', $quality->getWeaknesses(), true)) { $recommendations[] = new PreviewRecommendation( 'low_quality_images', 'Immagini di bassa qualità', PreviewRecommendation::TYPE_QUALITY, 'images', 'high' ); } if ($confidence !== null && in_array('publisher', $confidence->getConflictingFields(), true)) { $recommendations[] = new PreviewRecommendation( 'conflicting_publisher', 'Editore in conflitto', PreviewRecommendation::TYPE_CONFLICT, 'publisher', 'medium' ); } if ($this->requiresIsbn($productScore) && ! $this->hasIsbn($productScore)) { $recommendations[] = new PreviewRecommendation( 'missing_isbn', 'ISBN mancante', PreviewRecommendation::TYPE_DATA, 'identifiers', 'medium' ); } if ($quality !== null && in_array('metadata_richness', $quality->getWeaknesses(), true)) { $recommendations[] = new PreviewRecommendation( 'weak_metadata', 'Metadati poco completi', PreviewRecommendation::TYPE_METADATA, null, 'medium' ); } if ($confidence !== null && $confidence->getOverallScore() < $this->lowConfidenceThreshold) { $recommendations[] = new PreviewRecommendation( 'low_confidence', 'Affidabilità bassa', PreviewRecommendation::TYPE_QUALITY, null, 'high' ); } return $recommendations; } private function requiresIsbn(?ProductScore $productScore): bool { if ($productScore === null) { return false; } $attributesField = $productScore->getField('attributes'); if ($attributesField === null || ! is_array($attributesField->getValue())) { return false; } foreach ($attributesField->getValue() as $attribute) { if (! $attribute instanceof AttributeDTO || strtolower(trim($attribute->getName())) !== 'media_type') { continue; } return MediaType::normalize($attribute->getValue()) === MediaType::BOOK; } return false; } private function isMissing(?ProductScore $productScore, string $field): bool { return $productScore === null || $productScore->getField($field) === null; } private function hasIsbn(?ProductScore $productScore): bool { if ($productScore === null || $productScore->getField('identifiers') === null) { return false; } $identifiers = $productScore->getField('identifiers')->getValue(); if (! is_array($identifiers)) { return false; } return ! empty($identifiers['isbn']) || ! empty($identifiers['isbn10']) || ! empty($identifiers['isbn13']); } }