<?php

namespace Tests\Feature;

use App\Enums\LandingPageVersion;
use App\Jobs\GenerateCatalogLandingPagesJob;
use App\Models\LandingPage;
use App\Models\LandingPageGeneration;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Bus;
use Tests\TestCase;

class CatalogLandingPageGenerationControllerTest extends TestCase
{
    use RefreshDatabase;

    public function test_guests_are_redirected_from_the_catalog_index(): void
    {
        $this->get(route('catalog-landing-pages.index'))
            ->assertRedirect(route('login'));
    }

    public function test_authenticated_users_can_view_the_create_form(): void
    {
        $this->actingAs(User::factory()->create());

        $this->get(route('catalog-landing-pages.create'))
            ->assertOk()
            ->assertSee('New Catalog Landing Page')
            ->assertSee('brand name for this catalog')
            ->assertDontSee('Product URLs')
            ->assertDontSee('Unique layouts (six different page structures)')
            ->assertDontSee('HTML template (keep this structure for all six)');
    }

    public function test_authenticated_users_can_download_the_products_json_template(): void
    {
        $this->actingAs(User::factory()->create());

        $response = $this->get(route('catalog-landing-pages.products-json-template'));

        $response->assertOk();
        $response->assertHeader('content-type', 'application/json; charset=UTF-8');
        $response->assertDownload('catalog-products-template.json');
        $response->assertSee('"products"', false);
        $response->assertSee('"name"', false);
        $response->assertSee('"image_url"', false);
    }

    public function test_guests_cannot_download_the_products_json_template(): void
    {
        $this->get(route('catalog-landing-pages.products-json-template'))
            ->assertRedirect(route('login'));
    }

    public function test_catalog_store_route_is_not_available(): void
    {
        Bus::fake();

        $this->actingAs(User::factory()->create())
            ->post('/catalog-landing-pages', [
                'brand_name' => 'Admedia',
                'product_urls' => 'https://example.com/product',
            ])
            ->assertMethodNotAllowed();

        $this->assertSame(0, LandingPageGeneration::query()->count());
        Bus::assertNothingDispatched();
    }

    public function test_landing_pages_hub_is_available_without_legacy_resource_routes(): void
    {
        $user = User::factory()->create();
        $generation = LandingPageGeneration::factory()->create([
            'user_id' => $user->id,
        ]);

        $this->actingAs($user)
            ->get('/landing-pages')
            ->assertOk();

        $this->actingAs($user)
            ->get('/landing-pages/create')
            ->assertNotFound();

        $this->actingAs($user)
            ->post('/landing-pages', [
                'brand_name' => 'Admedia',
                'product_urls' => 'https://example.com/product',
                'layout_mode' => 'unique',
            ])
            ->assertMethodNotAllowed();

        $this->actingAs($user)
            ->get('/landing-pages/'.$generation->id)
            ->assertNotFound();

        $this->assertSame(1, LandingPageGeneration::query()->count());
    }

    public function test_non_catalog_generations_do_not_appear_on_the_catalog_index(): void
    {
        $user = User::factory()->create();
        LandingPageGeneration::factory()->catalog()->create([
            'user_id' => $user->id,
            'brand_name' => 'Catalog Brand',
        ]);
        LandingPageGeneration::factory()->create([
            'user_id' => $user->id,
            'brand_name' => 'Unique Brand',
        ]);

        $this->actingAs($user)
            ->get(route('landing-pages.index', ['tab' => 'catalog']))
            ->assertOk()
            ->assertSee('Catalog Brand')
            ->assertDontSee('Unique Brand');
    }

    public function test_index_and_show_display_clickable_live_urls(): void
    {
        $user = User::factory()->create();
        $generation = LandingPageGeneration::factory()
            ->catalog()
            ->withPartnerWebsite('https://rateit.com')
            ->withAffiliateTracking()
            ->create([
                'user_id' => $user->id,
                'status' => 'completed',
            ]);

        $page = LandingPage::factory()
            ->for($generation, 'generation')
            ->completed()
            ->create([
                'version' => LandingPageVersion::Benefits,
            ]);

        $generation->update([
            'published_landing_page_id' => $page->id,
            'published_at' => now(),
        ]);
        $page->setRelation('generation', $generation->fresh());

        $liveUrl = $page->partnerPreviewUrl();
        $this->assertNotNull($liveUrl);

        $this->actingAs($user)
            ->get(route('landing-pages.index', ['tab' => 'catalog']))
            ->assertOk()
            ->assertSee($liveUrl, false)
            ->assertSee('aria-label="Live URL"', false);

        $this->actingAs($user)
            ->get(route('catalog-landing-pages.show', $generation))
            ->assertOk()
            ->assertSee($liveUrl, false)
            ->assertSee('Live URL', false);
    }

    public function test_live_urls_stay_hidden_until_affiliate_tracking_is_saved(): void
    {
        $user = User::factory()->create();
        $generation = LandingPageGeneration::factory()
            ->catalog()
            ->withPartnerWebsite('https://rateit.com')
            ->create([
                'user_id' => $user->id,
                'status' => 'completed',
            ]);

        LandingPage::factory()
            ->for($generation, 'generation')
            ->completed()
            ->create([
                'version' => LandingPageVersion::Benefits,
            ]);

        $this->actingAs($user)
            ->get(route('landing-pages.index', ['tab' => 'catalog']))
            ->assertOk()
            ->assertDontSee('Live URL', false)
            ->assertSee('Affiliate tracking', false);

        $this->actingAs($user)
            ->get(route('catalog-landing-pages.show', $generation))
            ->assertOk()
            ->assertDontSee('dev.rateit.com', false)
            ->assertSee('Affiliate tracking', false);
    }

    public function test_analytics_and_publish_buttons_stay_hidden_until_affiliate_tracking_is_saved(): void
    {
        $user = User::factory()->create();
        $generation = LandingPageGeneration::factory()
            ->catalog()
            ->withPartnerWebsite()
            ->create([
                'user_id' => $user->id,
                'status' => 'completed',
            ]);

        $page = LandingPage::factory()
            ->for($generation, 'generation')
            ->completed()
            ->create([
                'version' => LandingPageVersion::Benefits,
            ]);

        $this->actingAs($user)
            ->get(route('catalog-landing-pages.show', $generation))
            ->assertOk()
            ->assertDontSee('<i class="bi bi-bar-chart"></i>Analytics</a>', false)
            ->assertDontSee(route('catalog-landing-pages.publish', [$generation, $page]), false);

        $this->actingAs($user)
            ->from(route('catalog-landing-pages.show', $generation))
            ->patch(route('catalog-landing-pages.affiliate.update', $generation), [
                'admedia_campaign_id' => '122609',
                'affiliate_key' => 'rateit_shop_CPA',
            ])
            ->assertRedirect(route('catalog-landing-pages.show', $generation));

        $this->actingAs($user)
            ->get(route('catalog-landing-pages.show', $generation))
            ->assertOk()
            ->assertSee('<i class="bi bi-bar-chart"></i>Analytics</a>', false)
            ->assertSee(route('catalog-landing-pages.publish', [$generation, $page]), false);
    }

    public function test_owner_can_save_affiliate_tracking_for_a_completed_catalog_generation(): void
    {
        $user = User::factory()->create();
        $generation = LandingPageGeneration::factory()
            ->catalog()
            ->withPartnerWebsite()
            ->create([
                'user_id' => $user->id,
                'status' => 'completed',
            ]);

        LandingPage::factory()
            ->for($generation, 'generation')
            ->completed()
            ->create([
                'version' => LandingPageVersion::Benefits,
            ]);

        $this->actingAs($user)
            ->from(route('catalog-landing-pages.show', $generation))
            ->patch(route('catalog-landing-pages.affiliate.update', $generation), [
                'admedia_campaign_id' => '122609',
                'affiliate_key' => 'rateit_shop_CPA',
            ])
            ->assertRedirect(route('catalog-landing-pages.show', $generation))
            ->assertSessionHas('status', 'Affiliate tracking saved.');

        $generation->refresh();

        $this->assertSame('122609', $generation->admedia_campaign_id);
        $this->assertSame('rateit_shop_CPA', $generation->affiliate_key);
        $this->assertTrue($generation->hasAffiliateTracking());
    }

    public function test_owner_can_save_tracking_pixels_for_a_completed_catalog_generation(): void
    {
        $user = User::factory()->create();
        $generation = LandingPageGeneration::factory()
            ->catalog()
            ->withPartnerWebsite()
            ->create([
                'user_id' => $user->id,
                'status' => 'completed',
            ]);

        LandingPage::factory()
            ->for($generation, 'generation')
            ->completed()
            ->create([
                'version' => LandingPageVersion::Benefits,
            ]);

        $this->actingAs($user)
            ->from(route('catalog-landing-pages.show', $generation))
            ->patch(route('catalog-landing-pages.pixels.update', $generation), [
                'google_conversion_send_to' => 'AW-17926447003/fOwtCJz32vocEJu__-NC',
                'meta_pixel_id' => '2862655720757421',
            ])
            ->assertRedirect(route('catalog-landing-pages.show', $generation))
            ->assertSessionHas('status', 'Tracking pixels saved.');

        $generation->refresh();

        $this->assertSame('AW-17926447003/fOwtCJz32vocEJu__-NC', $generation->google_conversion_send_to);
        $this->assertSame('2862655720757421', $generation->meta_pixel_id);
    }

    public function test_completed_catalog_show_page_displays_the_tracking_pixels_button(): void
    {
        $user = User::factory()->create();
        $generation = LandingPageGeneration::factory()
            ->catalog()
            ->withPartnerWebsite()
            ->create([
                'user_id' => $user->id,
                'status' => 'completed',
            ]);

        LandingPage::factory()
            ->for($generation, 'generation')
            ->completed()
            ->create([
                'version' => LandingPageVersion::Benefits,
            ]);

        $this->actingAs($user)
            ->get(route('catalog-landing-pages.show', $generation))
            ->assertOk()
            ->assertSee('Tracking pixels', false)
            ->assertSee(route('catalog-landing-pages.pixels.update', $generation), false);
    }

    public function test_returns_404_when_saving_pixels_for_an_incomplete_catalog_generation(): void
    {
        $user = User::factory()->create();
        $generation = LandingPageGeneration::factory()
            ->catalog()
            ->create([
                'user_id' => $user->id,
                'status' => 'discovering',
            ]);

        $this->actingAs($user)
            ->patch(route('catalog-landing-pages.pixels.update', $generation), [
                'meta_pixel_id' => '2862655720757421',
            ])
            ->assertNotFound();
    }

    public function test_the_generated_store_rejects_catalog_layout_mode(): void
    {
        Bus::fake();

        $this->actingAs(User::factory()->create())
            ->post('/landing-pages', [
                'brand_name' => 'Admedia',
                'product_urls' => 'https://example.com/product',
                'layout_mode' => 'catalog',
            ])
            ->assertMethodNotAllowed();

        $this->assertSame(0, LandingPageGeneration::query()->count());
        Bus::assertNothingDispatched();
    }

    public function test_owner_can_view_catalog_research_ranking_modal_on_show_page(): void
    {
        $user = User::factory()->create();
        $generation = LandingPageGeneration::factory()->catalog()->create([
            'user_id' => $user->id,
            'status' => 'completed',
            'catalog' => [
                'research' => [
                    'products' => [
                        [
                            'rank' => 1,
                            'name' => 'Office Chair',
                            'url' => 'https://example.com/chair',
                            'ranking_source' => 'ai',
                            'matched_keyword' => 'office chair',
                            'keyword_search_volume' => 201000,
                            'keyword_match_source' => 'ai',
                            'keyword_match_reason' => 'This is an office chair.',
                            'selection_reason' => 'Most reviewed pick.',
                            'ranking_reason' => 'Ranked #1 because of review volume.',
                        ],
                    ],
                    'ranking' => [
                        'source' => 'ai',
                        'selected_count' => 1,
                        'keywords_enabled' => true,
                    ],
                ],
            ],
        ]);

        $this->actingAs($user)
            ->get(route('catalog-landing-pages.show', $generation))
            ->assertOk()
            ->assertSee('View ranking')
            ->assertSee('Research JSON')
            ->assertSee('Office Chair')
            ->assertSee('Ranked #1 because of review volume.');
    }

    public function test_users_cannot_view_another_users_catalog_generation(): void
    {
        $owner = User::factory()->create();
        $other = User::factory()->create();

        $generation = LandingPageGeneration::factory()->catalog()->create([
            'user_id' => $owner->id,
        ]);

        $this->actingAs($other)
            ->get(route('catalog-landing-pages.show', $generation))
            ->assertForbidden();
    }

    public function test_catalog_show_returns_not_found_for_generated_layout_modes(): void
    {
        $user = User::factory()->create();
        $generation = LandingPageGeneration::factory()->create([
            'user_id' => $user->id,
        ]);

        $this->actingAs($user)
            ->get(route('catalog-landing-pages.show', $generation))
            ->assertNotFound();
    }

    public function test_owner_can_retry_a_completed_catalog_page(): void
    {
        Bus::fake();

        $user = User::factory()->create();
        $catalog = [
            'Brand' => 'garden-tools-v1',
            'products' => [
                ['name' => 'Watering Can', 'retailer_url' => 'https://example.com/can'],
            ],
        ];
        $generation = LandingPageGeneration::factory()->catalog()->create([
            'user_id' => $user->id,
            'status' => 'completed',
            'catalog' => $catalog,
        ]);
        $page = LandingPage::factory()->create([
            'landing_page_generation_id' => $generation->id,
            'status' => 'completed',
            'title' => 'Old title',
            'html' => '<section>Old</section>',
            'css' => 'body { color: red; }',
            'js' => 'console.log("old")',
        ]);

        $this->actingAs($user)
            ->post(route('catalog-landing-pages.retry', [$generation, $page]))
            ->assertRedirect(route('catalog-landing-pages.show', $generation));

        $page->refresh();
        $generation->refresh();

        $this->assertSame('queued', $page->status);
        $this->assertNull($page->html);
        $this->assertSame('queued', $generation->status);
        $this->assertSame($catalog, $generation->catalog);

        Bus::assertDispatched(
            GenerateCatalogLandingPagesJob::class,
            fn (GenerateCatalogLandingPagesJob $job) => $job->generationId === $generation->id && $job->landingPageId === $page->id,
        );
    }

    public function test_guests_are_redirected_from_the_template_preview(): void
    {
        $this->get(route('catalog-landing-pages.template-preview', 'template-1'))
            ->assertRedirect(route('login'));
    }

    public function test_authenticated_users_can_preview_a_shared_catalog_template(): void
    {
        $this->actingAs(User::factory()->create())
            ->get(route('catalog-landing-pages.template-preview', 'template-1'))
            ->assertOk()
            ->assertHeader('Content-Type', 'text/html; charset=UTF-8')
            ->assertSee('<html', false);
    }

    public function test_template_preview_returns_not_found_for_unknown_templates(): void
    {
        $this->actingAs(User::factory()->create())
            ->get(route('catalog-landing-pages.template-preview', 'missing'))
            ->assertNotFound();
    }

    public function test_preview_assembles_html_css_and_js_from_the_database(): void
    {
        $user = User::factory()->create();
        $generation = LandingPageGeneration::factory()->catalog()->create([
            'user_id' => $user->id,
            'status' => 'completed',
        ]);
        $page = LandingPage::factory()->create([
            'landing_page_generation_id' => $generation->id,
            'status' => 'completed',
            'title' => 'Catalog page',
            'html' => '<body class="dermstore-theme aggressive-variant"><article class="catalog-product"><h1>Watering Can</h1></article></body>',
            'css' => '.catalog-page { color: navy; }',
            'js' => 'console.log("catalog")',
        ]);

        $this->actingAs($user)
            ->get(route('catalog-landing-pages.preview', [$generation, $page]))
            ->assertOk()
            ->assertSee('<h1>Watering Can</h1>', false)
            ->assertSee('<body class="dermstore-theme aggressive-variant">', false)
            ->assertSee('.catalog-page { color: navy; }', false)
            ->assertSee('console.log("catalog")', false);
    }

    public function test_preview_keeps_the_template_head_on_a_full_document(): void
    {
        $user = User::factory()->create();
        $generation = LandingPageGeneration::factory()->catalog()->create([
            'user_id' => $user->id,
            'status' => 'completed',
        ]);
        $page = LandingPage::factory()->create([
            'landing_page_generation_id' => $generation->id,
            'status' => 'completed',
            'title' => 'Catalog page',
            'html' => <<<'HTML'
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Keep me</title>
    <link rel="stylesheet" href="style.css">
</head>
<body class="bg-light-gradient">
    <h1>Watering Can</h1>
</body>
</html>
HTML,
            'css' => '.header { color: red; }',
            'js' => 'console.log("catalog")',
        ]);

        $this->actingAs($user)
            ->get(route('catalog-landing-pages.preview', [$generation, $page]))
            ->assertOk()
            ->assertSee('<title>Keep me</title>', false)
            ->assertSee('<link rel="stylesheet" href="style.css">', false)
            ->assertSee('<body class="bg-light-gradient">', false)
            ->assertSee('.header { color: red; }', false);
    }

    public function test_show_redirects_to_the_wizard_when_setup_is_incomplete(): void
    {
        $user = User::factory()->create();
        $generation = LandingPageGeneration::factory()->catalog()->create([
            'user_id' => $user->id,
            'status' => 'awaiting_template',
            'catalog' => [
                'research' => [
                    'source' => 'json',
                    'products' => [
                        ['name' => 'Sample Product', 'url' => 'https://example.com/p/1'],
                    ],
                ],
            ],
        ]);

        $this->actingAs($user)
            ->get(route('catalog-landing-pages.show', $generation))
            ->assertRedirect(route('catalog-landing-pages.create', ['generation' => $generation->id]));
    }

    public function test_show_page_uses_display_status_when_pages_are_complete_but_generation_is_queued(): void
    {
        $user = User::factory()->create();
        $generation = LandingPageGeneration::factory()->catalog()->create([
            'user_id' => $user->id,
            'status' => 'queued',
        ]);

        LandingPage::factory()->create([
            'landing_page_generation_id' => $generation->id,
            'version' => LandingPageVersion::Benefits,
            'status' => 'completed',
            'html' => '<html><body><h1>Ready</h1></body></html>',
        ]);

        LandingPage::factory()->create([
            'landing_page_generation_id' => $generation->id,
            'version' => LandingPageVersion::Comparison,
            'status' => 'completed',
            'html' => '<html><body><h1>Ready too</h1></body></html>',
        ]);

        $this->actingAs($user)
            ->get(route('catalog-landing-pages.show', $generation))
            ->assertOk()
            ->assertSee('id="generation-status"', false)
            ->assertSee('>completed<', false)
            ->assertSee('id="generation-details-status"', false)
            ->assertDontSee('mb-catalog-page-preview is-empty', false);
    }
}
