<?php

namespace Tests\Unit\Services\Scraping;

use App\Services\Scraping\PuppeteerListingScraper;
use Illuminate\Support\Facades\Process;
use Tests\TestCase;

class PuppeteerListingScraperTest extends TestCase
{
    public function test_it_returns_a_disabled_result_when_puppeteer_is_off(): void
    {
        config(['scraping.puppeteer.enabled' => false]);

        $result = (new PuppeteerListingScraper)->scrape('https://shop.example.com/collections/chairs');

        $this->assertFalse($result->succeeded());
        $this->assertSame([], $result->products);
        $this->assertSame('Puppeteer scraping is disabled.', $result->error);
    }

    public function test_it_parses_json_from_the_node_script(): void
    {
        config([
            'scraping.puppeteer.enabled' => true,
            'scraping.puppeteer.node_binary' => 'node',
            'scraping.puppeteer.listing_script' => 'scripts/scraping/scrape-listing.js',
            'scraping.puppeteer.timeout_seconds' => 30,
            'scraping.puppeteer.browser_channel' => 'chrome',
            'scraping.puppeteer.browser_engine' => 'auto',
            'scraping.puppeteer.browser_engines' => 'chrome,firefox,chromium',
            'scraping.puppeteer.headless' => 'false',
            'scraping.puppeteer.proxy' => 'http://proxy.example:8080',
            'scraping.puppeteer.proxy_username' => 'proxy-user',
            'scraping.puppeteer.proxy_password' => 'proxy-pass',
            'scraping.puppeteer.cookies_file' => null,
        ]);

        Process::fake([
            '*scrape-listing.js*' => Process::result(json_encode([
                'url' => 'https://shop.example.com/collections/chairs',
                'source' => 'puppeteer',
                'browser_engine' => 'firefox',
                'engines_tried' => ['chrome', 'firefox'],
                'products' => [
                    [
                        'name' => 'Ergo Chair',
                        'url' => 'https://shop.example.com/products/ergo-chair',
                        'price' => '$249.99',
                        'rating' => '4.6',
                        'review_count' => '842',
                        'image_url' => 'https://shop.example.com/images/ergo-chair.jpg',
                        'badges' => ['Bestseller'],
                    ],
                ],
                'error' => null,
            ], JSON_THROW_ON_ERROR)),
        ]);

        $result = (new PuppeteerListingScraper)->scrape('https://shop.example.com/collections/chairs');

        $this->assertTrue($result->succeeded());
        $this->assertCount(1, $result->products);
        $this->assertSame('Ergo Chair', $result->products[0]->name);
        $this->assertSame('$249.99', $result->products[0]->price);
        $this->assertSame(['Bestseller'], $result->products[0]->badges);

        $this->assertSame('firefox', $result->browserEngine);
        $this->assertSame(['chrome', 'firefox'], $result->enginesTried);

        Process::assertRan(function ($process) {
            return ($process->environment['SCRAPING_BROWSER_CHANNEL'] ?? null) === 'chrome'
                && ($process->environment['SCRAPING_BROWSER_ENGINE'] ?? null) === 'auto'
                && ($process->environment['SCRAPING_BROWSER_ENGINES'] ?? null) === 'chrome,firefox,chromium'
                && ($process->environment['SCRAPING_HEADLESS'] ?? null) === 'false'
                && ($process->environment['SCRAPING_PROXY'] ?? null) === 'http://proxy.example:8080'
                && ($process->environment['SCRAPING_PROXY_USERNAME'] ?? null) === 'proxy-user'
                && ($process->environment['SCRAPING_PROXY_PASSWORD'] ?? null) === 'proxy-pass'
                && ! array_key_exists('SCRAPING_COOKIES_FILE', $process->environment);
        });
    }

    public function test_it_surfaces_process_failures(): void
    {
        config([
            'scraping.puppeteer.enabled' => true,
            'scraping.puppeteer.node_binary' => 'node',
            'scraping.puppeteer.listing_script' => 'scripts/scraping/scrape-listing.js',
            'scraping.puppeteer.timeout_seconds' => 30,
        ]);

        Process::fake([
            '*scrape-listing.js*' => Process::result('', errorOutput: 'node: command failed', exitCode: 1),
        ]);

        $result = (new PuppeteerListingScraper)->scrape('https://shop.example.com/collections/chairs');

        $this->assertFalse($result->succeeded());
        $this->assertSame('node: command failed', $result->error);
    }

    public function test_it_parses_structured_errors_from_failed_process_stdout(): void
    {
        config([
            'scraping.puppeteer.enabled' => true,
            'scraping.puppeteer.node_binary' => 'node',
            'scraping.puppeteer.listing_script' => 'scripts/scraping/scrape-listing.js',
            'scraping.puppeteer.timeout_seconds' => 30,
        ]);

        Process::fake([
            '*scrape-listing.js*' => Process::result(json_encode([
                'url' => 'https://www.marshalls.com/us/store/shop/clearance/_/N-3951437597',
                'source' => 'puppeteer',
                'site' => 'marshalls',
                'products' => [],
                'error' => 'Marshalls blocked automated access.',
            ], JSON_THROW_ON_ERROR), exitCode: 1),
        ]);

        $result = (new PuppeteerListingScraper)->scrape('https://www.marshalls.com/us/store/shop/clearance/_/N-3951437597');

        $this->assertFalse($result->succeeded());
        $this->assertSame('Marshalls blocked automated access.', $result->error);
        $this->assertSame([], $result->products);
    }
}
