<?php

namespace Modules\ProductCompat\Entities\Enrichment\Providers;

use App\Product;
use Modules\ProductCompat\Entities\Enrichment\EnrichmentProvider;
use Modules\ProductCompat\Entities\Enrichment\EnrichmentResult;
use Modules\ProductCompat\Entities\Services\AiExtractionService;
use Modules\ProductCompat\Entities\Services\SearchTextCollector;
use Modules\ProductCompat\Entities\Services\Settings;

/**
 * Optional AI enrichment provider for the CLASSIC (first-win) pipeline. Off by
 * default — enable via the `ai_provider_enabled` setting. It runs the collector
 * in product-context-only mode (no upstream provider results) plus the AI
 * extraction service, and maps the structured candidates into a normal
 * EnrichmentResult (with the rich fields carried through for the aggressive
 * pipeline).
 *
 * The aggressive pipeline (AggressiveEnrichmentService) drives collector +
 * extraction directly; this provider is the classic-pipeline entry point.
 */
class AiEnrichProvider implements EnrichmentProvider
{
    protected SearchTextCollector $collector;
    protected AiExtractionService $extractor;

    public function __construct(?SearchTextCollector $collector = null, ?AiExtractionService $extractor = null)
    {
        $this->collector = $collector ?? new SearchTextCollector();
        $this->extractor = $extractor ?? new AiExtractionService();
    }

    public function key(): string
    {
        return 'ai';
    }

    /**
     * Providers get a Product only in fetch(), not a business, so availability
     * here checks only the master setting plus the class/table guards inside the
     * extractor (available() with a 0 business is a cheap structural check).
     * Per-product configuration is verified in fetch().
     */
    public function isAvailable(): bool
    {
        if (! Settings::bool('ai_provider_enabled', false)) {
            return false;
        }

        return class_exists(\Modules\AiCore\Entities\Services\AiClient::class)
            && class_exists(\Modules\AiCore\Entities\AiProvider::class);
    }

    public function fetch(Product $product): EnrichmentResult
    {
        if (! $this->extractor->available((int) $product->business_id)) {
            return EnrichmentResult::fail('ai_unavailable: AiCore not configured for this business');
        }

        // Product-context-only mode: no upstream provider results, so the
        // collector runs its own extra searches to build the source blocks.
        $sources = $this->collector->collect($product, []);

        $existing = $this->snapshot($product);
        $result = $this->extractor->extract($product, $sources, $existing);

        if (empty($result['ok'])) {
            return EnrichmentResult::fail('ai_error: ' . (string) ($result['error'] ?? 'unknown'));
        }

        $data = $result['data'] ?? [];

        $candidates = [
            'part_numbers'  => $data['part_numbers']  ?? [],
            'device_models' => $data['device_models'] ?? [],
            'barcodes'      => $data['barcodes']      ?? [],
        ];

        // Carry the AI's product-level output + corrections through as rich data.
        $rich = array_merge(
            (array) ($data['product'] ?? []),
            ['corrections' => $data['corrections'] ?? []]
        );

        return new EnrichmentResult(true, $candidates, [
            'model_used'  => $result['model_used'] ?? null,
            'source_ids'  => array_map(fn ($s) => $s['id'] ?? null, $sources),
        ], null, $rich);
    }

    /** Minimal existing-data snapshot for the extraction prompt. */
    protected function snapshot(Product $product): array
    {
        return [
            'name'        => (string) $product->name,
            'sku'         => (string) $product->sku,
            'brand'       => trim((string) optional($product->brand)->name),
            'description' => trim(strip_tags((string) $product->product_description)),
        ];
    }
}
