<?php

namespace Tests\Feature\Jobs;

use App\Contracts\CatalogProductRanker;
use App\Contracts\KeywordResearchService;
use App\Enums\LandingPageLayoutMode;
use App\Jobs\DiscoverCatalogProductsJob;
use App\Models\LandingPageGeneration;
use App\Models\User;
use App\Services\AI\CatalogWebsiteResearch;
use App\Services\CatalogTemplateLocator;
use App\Services\Keywords\CatalogKeywordSeedResolver;
use App\Services\Keywords\KeywordCandidateEnricher;
use App\Services\Keywords\KeywordIdeaCurator;
use App\Services\Ranking\CatalogProductRankingExplainer;
use App\Services\Scraping\CatalogListingProductValidator;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Laravel\Ai\StructuredAnonymousAgent;
use Tests\TestCase;

class DiscoverCatalogProductsJobTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();

        $this->mock(CatalogListingProductValidator::class, function ($mock): void {
            $mock->shouldReceive('validateAndEnrich')
                ->andReturnUsing(fn (array $candidates, bool $trustProvidedImages = false): array => $candidates);
        });
    }

    public function test_it_stores_ranked_products_and_waits_when_fewer_than_five_are_selected(): void
    {
        config(['scraping.ranking.enabled' => false]);

        Http::preventStrayRequests();
        Http::fake([
            'https://shop.example.com/robots.txt' => Http::response("User-agent: *\nDisallow:\n"),
            'https://shop.example.com/outdoor/tents' => Http::response('<html><a href="/p/1">One</a></html>'),
            'https://shop.example.com/p/1' => Http::response(
                '<html><head><meta property="og:image" content="https://cdn.example.com/one.jpg"></head><body>One</body></html>'
            ),
        ]);

        StructuredAnonymousAgent::fake([
            ['products' => [
                ['name' => 'Dome', 'url' => 'https://shop.example.com/p/1', 'popularity_note' => '4.8 stars'],
            ]],
        ]);

        $generation = LandingPageGeneration::factory()->create([
            'user_id' => User::factory()->create()->id,
            'status' => 'discovering',
            'layout_mode' => LandingPageLayoutMode::Catalog,
            'brand_url' => 'https://shop.example.com',
            'catalog' => [
                'research' => [
                    'category' => 'Outdoor',
                    'subcategory' => 'Tents',
                    'subcategories' => [
                        ['name' => 'Tents', 'url' => 'https://shop.example.com/outdoor/tents'],
                    ],
                    'selected_subcategories' => [
                        ['name' => 'Tents', 'url' => 'https://shop.example.com/outdoor/tents'],
                    ],
                ],
            ],
        ]);

        $this->runJob($generation->id);

        $generation->refresh();

        $this->assertSame('awaiting_subcategory', $generation->status);
        $this->assertCount(1, $generation->catalogResearch()['products']);
        $this->assertSame('no_products', $generation->catalogResearch()['empty_reason']);
        $this->assertArrayHasKey('ranking_reason', $generation->catalogResearch()['products'][0]);
        $this->assertArrayHasKey('ranking_signals', $generation->catalogResearch()['products'][0]);
    }

    public function test_json_import_continues_when_two_valid_products_are_uploaded(): void
    {
        config(['scraping.ranking.enabled' => false]);

        $this->mock(CatalogTemplateLocator::class, function ($mock): void {
            $mock->shouldReceive('slots')->andReturn(['hero' => 'template']);
            $mock->shouldReceive('sharedTemplates')->andReturn(['base' => 'layout']);
        });

        $generation = LandingPageGeneration::factory()->create([
            'user_id' => User::factory()->create()->id,
            'status' => 'discovering',
            'layout_mode' => LandingPageLayoutMode::Catalog,
            'brand_url' => 'https://shop.example.com',
            'catalog' => [
                'research' => [
                    'source' => 'json',
                    'uploaded_products' => [
                        [
                            'name' => 'Product 1',
                            'url' => 'https://shop.example.com/p/1',
                            'price' => '$19.99',
                            'image_url' => 'https://cdn.example.com/1.jpg',
                        ],
                        [
                            'name' => 'Product 2',
                            'url' => 'https://shop.example.com/p/2',
                            'price' => '$29.99',
                            'image_url' => 'https://cdn.example.com/2.jpg',
                        ],
                    ],
                ],
            ],
        ]);

        $this->runJob($generation->id);

        $generation->refresh();

        $this->assertSame('awaiting_template', $generation->status);
        $this->assertCount(2, $generation->catalogResearch()['products']);
        $this->assertSame([
            'https://shop.example.com/p/1',
            'https://shop.example.com/p/2',
        ], $generation->product_urls);
    }

    public function test_json_import_waits_when_one_product_remains(): void
    {
        config(['scraping.ranking.enabled' => false]);

        $generation = LandingPageGeneration::factory()->create([
            'user_id' => User::factory()->create()->id,
            'status' => 'discovering',
            'layout_mode' => LandingPageLayoutMode::Catalog,
            'brand_url' => 'https://shop.example.com',
            'catalog' => [
                'research' => [
                    'source' => 'json',
                    'uploaded_products' => [[
                        'name' => 'Product 1',
                        'url' => 'https://shop.example.com/p/1',
                        'price' => '$19.99',
                        'image_url' => 'https://cdn.example.com/1.jpg',
                    ]],
                ],
            ],
        ]);

        $this->runJob($generation->id);

        $generation->refresh();

        $this->assertSame('awaiting_products', $generation->status);
        $this->assertCount(1, $generation->catalogResearch()['products']);
        $this->assertSame('no_products', $generation->catalogResearch()['empty_reason']);
    }

    public function test_it_keeps_only_same_host_products_from_ai_picks(): void
    {
        config(['scraping.ranking.enabled' => false]);

        Http::preventStrayRequests();
        Http::fake([
            'https://shop.example.com/robots.txt' => Http::response("User-agent: *\nDisallow:\n"),
            'https://shop.example.com' => Http::response('<html></html>'),
            'https://shop.example.com/outdoor/tents' => Http::response(
                '<html><a href="/p/1">One</a></html>'
            ),
            'https://shop.example.com/p/*' => Http::response(
                '<html><head><meta property="og:image" content="https://cdn.example.com/one.jpg"></head><body>One</body></html>'
            ),
        ]);

        StructuredAnonymousAgent::fake([
            ['products' => [
                ['name' => 'Tent', 'url' => 'https://amazon.example.com/tent', 'popularity_note' => 'Bestseller'],
                ['name' => 'Dome', 'url' => 'https://shop.example.com/p/1', 'popularity_note' => '4.8 stars'],
            ]],
        ]);

        $generation = LandingPageGeneration::factory()->create([
            'user_id' => User::factory()->create()->id,
            'status' => 'discovering',
            'layout_mode' => LandingPageLayoutMode::Catalog,
            'brand_url' => 'https://shop.example.com',
            'catalog' => [
                'research' => [
                    'category' => 'Outdoor',
                    'subcategory' => 'Tents',
                    'subcategories' => [
                        ['name' => 'Tents', 'url' => 'https://shop.example.com/outdoor/tents'],
                    ],
                    'selected_subcategories' => [
                        ['name' => 'Tents', 'url' => 'https://shop.example.com/outdoor/tents'],
                    ],
                ],
            ],
        ]);

        $this->runJob($generation->id);

        $generation->refresh();

        $this->assertSame('awaiting_subcategory', $generation->status);
        $this->assertCount(1, $generation->catalogResearch()['products']);
    }

    public function test_it_persists_keyword_research_when_google_ads_is_enabled(): void
    {
        config([
            'scraping.ranking.enabled' => false,
            'google-ads.enabled' => true,
        ]);

        $this->mock(KeywordResearchService::class, function ($mock): void {
            $mock->shouldReceive('ideasForSeeds')
                ->once()
                ->andReturn([
                    [
                        'term' => 'outdoor tent',
                        'avg_monthly_searches' => 50000,
                        'competition' => 'HIGH',
                    ],
                ]);
        });

        Http::preventStrayRequests();
        Http::fake([
            'https://shop.example.com/robots.txt' => Http::response("User-agent: *\nDisallow:\n"),
            'https://shop.example.com/outdoor/tents' => Http::response('<html><a href="/p/1">One</a></html>'),
            'https://shop.example.com/p/1' => Http::response(
                '<html><head><meta property="og:image" content="https://cdn.example.com/one.jpg"></head><body>One</body></html>'
            ),
        ]);

        StructuredAnonymousAgent::fake([
            ['products' => [
                ['name' => 'Dome', 'url' => 'https://shop.example.com/p/1', 'popularity_note' => '4.8 stars'],
            ]],
            ['products' => [[
                'index' => 1,
                'seeds' => ['outdoor tent', 'camping tent'],
            ]]],
        ]);

        $generation = LandingPageGeneration::factory()->create([
            'user_id' => User::factory()->create()->id,
            'status' => 'discovering',
            'layout_mode' => LandingPageLayoutMode::Catalog,
            'brand_name' => 'CampCo',
            'brand_url' => 'https://shop.example.com',
            'catalog' => [
                'research' => [
                    'category' => 'Outdoor',
                    'subcategory' => 'Tents',
                    'subcategories' => [
                        ['name' => 'Tents', 'url' => 'https://shop.example.com/outdoor/tents'],
                    ],
                    'selected_subcategories' => [
                        ['name' => 'Tents', 'url' => 'https://shop.example.com/outdoor/tents'],
                    ],
                ],
            ],
        ]);

        $this->runJob($generation->id);

        $generation->refresh();
        $research = $generation->catalogResearch();

        $this->assertNotEmpty($research['keyword_seeds']);
        $this->assertSame('outdoor tent', $research['keywords'][0]['term']);
        $this->assertTrue($research['ranking']['keywords_enabled']);
        $this->assertSame(['outdoor tent', 'camping tent'], $research['products'][0]['keyword_seeds_generated']['ai']);
        $this->assertNotEmpty($research['products'][0]['keyword_seeds_generated']['heuristic']);
    }

    private function runJob(int $generationId): void
    {
        (new DiscoverCatalogProductsJob($generationId))->handle(
            app(CatalogWebsiteResearch::class),
            app(CatalogTemplateLocator::class),
            app(CatalogProductRanker::class),
            app(KeywordResearchService::class),
            app(CatalogKeywordSeedResolver::class),
            app(KeywordCandidateEnricher::class),
            app(KeywordIdeaCurator::class),
            app(CatalogProductRankingExplainer::class),
            app(CatalogListingProductValidator::class),
        );
    }
}
