<?php

namespace Tests\Unit\Services\AI;

use App\Services\AI\AiCatalogProductRanker;
use App\Services\Ranking\HeuristicCatalogProductRanker;
use Laravel\Ai\StructuredAnonymousAgent;
use Tests\TestCase;

class AiCatalogProductRankerTest extends TestCase
{
    public function test_it_ranks_products_with_ai_and_merges_candidate_metadata(): void
    {
        config([
            'scraping.ranking.ai_enabled' => true,
            'scraping.ranking.limit' => 10,
        ]);

        StructuredAnonymousAgent::fake([
            ['products' => [
                ['url' => 'https://shop.example.com/p/3', 'rank' => 1, 'selection_reason' => 'Most reviewed', 'best_for' => 'Best Overall'],
                ['url' => 'https://shop.example.com/p/1', 'rank' => 2, 'selection_reason' => 'Strong value', 'best_for' => ''],
                ['url' => 'https://shop.example.com/p/2', 'rank' => 3, 'selection_reason' => 'Popular pick', 'best_for' => ''],
            ]],
        ]);

        $ranked = (new AiCatalogProductRanker(new HeuristicCatalogProductRanker))->rank(
            $this->candidates(3),
            'Outdoor',
            'Folding Chairs',
            'Use top-rated products.',
        );

        $this->assertCount(3, $ranked);
        $this->assertSame(1, $ranked[0]['rank']);
        $this->assertSame('Best Overall', $ranked[0]['best_for']);
        $this->assertSame('ai', $ranked[0]['ranking_source']);
        $this->assertSame('https://shop.example.com/p/3', $ranked[0]['url']);
        $this->assertSame('$30.00', $ranked[0]['price']);
        $this->assertSame('Most reviewed', $ranked[0]['selection_reason']);
    }

    public function test_it_falls_back_to_heuristic_when_ai_is_disabled(): void
    {
        config([
            'scraping.ranking.ai_enabled' => false,
            'scraping.ranking.limit' => 2,
        ]);

        $ranked = (new AiCatalogProductRanker(new HeuristicCatalogProductRanker))->rank(
            $this->candidates(3),
            'Outdoor',
            'Folding Chairs',
        );

        $this->assertCount(2, $ranked);
        $this->assertSame('heuristic', $ranked[0]['ranking_source']);
        $this->assertSame('https://shop.example.com/p/3', $ranked[0]['url']);
        $this->assertSame('Best Overall', $ranked[0]['best_for']);
    }

    public function test_it_falls_back_to_heuristic_when_ai_returns_unknown_urls(): void
    {
        config([
            'scraping.ranking.ai_enabled' => true,
            'scraping.ranking.limit' => 2,
        ]);

        StructuredAnonymousAgent::fake([
            ['products' => [
                ['url' => 'https://evil.example.com/p/99', 'rank' => 1, 'selection_reason' => 'Nope', 'best_for' => 'Best Overall'],
            ]],
        ]);

        $ranked = (new AiCatalogProductRanker(new HeuristicCatalogProductRanker))->rank(
            $this->candidates(3),
            'Outdoor',
            'Folding Chairs',
        );

        $this->assertCount(2, $ranked);
        $this->assertSame('heuristic', $ranked[0]['ranking_source']);
        $this->assertSame('https://shop.example.com/p/3', $ranked[0]['url']);
    }

    /**
     * @return list<array<string, mixed>>
     */
    private function candidates(int $count): array
    {
        $candidates = [];

        for ($i = 1; $i <= $count; $i++) {
            $candidates[] = [
                'name' => "Product {$i}",
                'url' => "https://shop.example.com/p/{$i}",
                'price' => '$'.(10 * $i).'.00',
                'rating' => (string) min(5, $i),
                'review_count' => (string) $i,
                'popularity_note' => "{$i} reviews",
            ];
        }

        return $candidates;
    }
}
