<?php

declare(strict_types=1);

/**
 * Feature tests for the new canonical route families introduced by the
 * Routing Unification spec (§3.2 Explore, §4 Blog/Pages, §6.1 redirects).
 */

use App\Models\Category;
use App\Models\ContentType;
use App\Models\Artwork;

beforeEach(function () {
    foreach (['wallpapers', 'skins', 'photography', 'other'] as $slug) {
        ContentType::query()->firstOrCreate(
            ['slug' => $slug],
            ['name' => ucfirst($slug)]
        );
    }
});

// ── /explore routes ──────────────────────────────────────────────────────────

it('GET /explore returns 200', function () {
    $this->get('/explore')->assertOk();
});

it('GET /explore contains "Explore" heading', function () {
    $this->get('/explore')->assertOk()->assertSee('Explore', false);
});

it('GET /explore/wallpapers redirects to the canonical /wallpapers route', function () {
    $this->get('/explore/wallpapers')->assertRedirect('/wallpapers')->assertStatus(301);
});

it('GET /explore/skins redirects to the canonical /skins route', function () {
    $this->get('/explore/skins')->assertRedirect('/skins')->assertStatus(301);
});

it('GET /explore/photography redirects to the canonical /photography route', function () {
    $this->get('/explore/photography')->assertRedirect('/photography')->assertStatus(301);
});

it('GET /explore/artworks returns 200', function () {
    $this->get('/explore/artworks')->assertOk();
});

it('GET /explore/other redirects to the canonical /other route', function () {
    $this->get('/explore/other')->assertRedirect('/other')->assertStatus(301);
});

it('GET /explore/wallpapers/trending redirects to the canonical /wallpapers route', function () {
    $this->get('/explore/wallpapers/trending')->assertRedirect('/wallpapers')->assertStatus(301);
});

it('GET /explore/wallpapers/latest redirects to the canonical sorted /wallpapers route', function () {
    $this->get('/explore/wallpapers/latest')->assertRedirect('/wallpapers?sort=latest')->assertStatus(301);
});

it('GET /explore/wallpapers/best redirects to the canonical sorted /wallpapers route', function () {
    $this->get('/explore/wallpapers/best')->assertRedirect('/wallpapers?sort=top-rated')->assertStatus(301);
});

it('GET /explore/wallpapers/new-hot redirects to the canonical sorted /wallpapers route', function () {
    $this->get('/explore/wallpapers/new-hot')->assertRedirect('/wallpapers?sort=fresh')->assertStatus(301);
});

it('/explore pages include canonical link tag', function () {
    $html = $this->get('/explore')->assertOk()->getContent();
    expect($html)->toContain('rel="canonical"');
});

it('/explore pages set robots index,follow', function () {
    $html = $this->get('/explore')->assertOk()->getContent();
    expect($html)->toContain('index,follow');
});

it('/explore hub page includes breadcrumb JSON-LD', function () {
    $html = $this->get('/explore')->assertOk()->getContent();
    expect($html)->toContain('BreadcrumbList');
});

// ── 301 redirects from legacy routes ─────────────────────────────────────────

it('GET /browse redirects to /explore with 301', function () {
    $this->get('/browse')->assertRedirect('/explore')->assertStatus(301);
});

it('GET /discover redirects to /discover/trending with 301', function () {
    $this->get('/discover')->assertRedirect('/discover/trending')->assertStatus(301);
});

it('GET /sections redirects to /categories with 301', function () {
    $this->get('/sections')->assertRedirect('/categories')->assertStatus(301);
});

it('GET /browse-categories redirects to /categories with 301', function () {
    $this->get('/browse-categories')->assertRedirect('/categories')->assertStatus(301);
});

it('legacy mixed-case category route redirects to the canonical category URL with 301', function () {
    $contentType = ContentType::query()->create([
        'name' => 'Skins',
        'slug' => 'skins',
    ]);

    $category = Category::query()->create([
        'content_type_id' => $contentType->id,
        'name' => 'BrowserBob',
        'slug' => 'browserbob',
    ]);

    $this->get('/Skins/BrowserBob/' . $category->id . '?ref=legacy')
        ->assertRedirect('/skins/browserbob?ref=legacy')
        ->assertStatus(301);
});

it('legacy nested category route redirects to the canonical nested category URL with 301', function () {
    $contentType = ContentType::query()->create([
        'name' => 'Skins',
        'slug' => 'skins',
    ]);

    $parent = Category::query()->create([
        'content_type_id' => $contentType->id,
        'name' => 'BrowserBob',
        'slug' => 'browserbob',
    ]);

    $child = Category::query()->create([
        'content_type_id' => $contentType->id,
        'parent_id' => $parent->id,
        'name' => 'sdsdsdsd',
        'slug' => 'sdsdsdsd',
    ]);

    $this->get('/Skins/BrowserBob/sdsdsdsd/' . $child->id)
        ->assertRedirect('/skins/browserbob/sdsdsdsd')
        ->assertStatus(301);
});

it('legacy category route falls back to /categories and preserves query string when no category matches', function () {
    $this->get('/Skins/does-not-exist/999999?source=old-site')
        ->assertRedirect('/categories?source=old-site')
        ->assertStatus(301);
});

it('legacy /category route redirects to the canonical category URL with 301', function () {
    $contentType = ContentType::query()->create([
        'name' => 'Skins',
        'slug' => 'skins',
    ]);

    $category = Category::query()->create([
        'content_type_id' => $contentType->id,
        'name' => 'BrowserBob',
        'slug' => 'browserbob',
    ]);

    $this->get('/category/skins/browserbob/' . $category->id . '?ref=legacy-category')
        ->assertRedirect('/skins/browserbob?ref=legacy-category')
        ->assertStatus(301);
});

it('legacy /category route falls back to /categories and preserves query string when no category matches', function () {
    $this->get('/category/skins/does-not-exist/999999?source=legacy-category')
        ->assertRedirect('/categories?source=legacy-category')
        ->assertStatus(301);
});

it('legacy rate.php artwork route redirects to the canonical artwork URL with 301', function () {
    $artwork = Artwork::factory()->create([
        'title' => 'Legacy Rated Artwork',
        'slug' => 'legacy-rated-artwork',
        'is_public' => true,
        'is_approved' => true,
        'published_at' => now()->subMinute(),
    ]);

    $this->get('/rate.php?skins=' . $artwork->id)
        ->assertRedirect(route('art.show', ['id' => $artwork->id, 'slug' => $artwork->slug]))
        ->assertStatus(301);
});

it('GET /today-in-history redirects to /discover/on-this-day with 301', function () {
    $this->get('/today-in-history')->assertRedirect('/discover/on-this-day')->assertStatus(301);
});

it('GET /members redirects to /creators/top with 301', function () {
    $this->get('/members')->assertRedirect('/creators/top')->assertStatus(301);
});

it('GET /explore/members redirects to /creators/top with 301', function () {
    $this->get('/explore/members')->assertRedirect('/creators/top')->assertStatus(301);
});

it('GET /latest-artworks redirects to /discover/fresh with 301', function () {
    $this->get('/latest-artworks')->assertRedirect('/discover/fresh')->assertStatus(301);
});

it('GET /today-downloads redirects to /downloads/today with 301', function () {
    $this->get('/today-downloads')->assertRedirect('/downloads/today')->assertStatus(301);
});

it('GET /monthly-commentators redirects to /comments/monthly with 301', function () {
    $this->get('/monthly-commentators')->assertRedirect('/comments/monthly')->assertStatus(301);
});

it('GET /top-favourites redirects to /discover/top-rated with 301', function () {
    $this->get('/top-favourites')->assertRedirect('/discover/top-rated')->assertStatus(301);
});

it('GET /downloads/today returns 200', function () {
    $this->get('/downloads/today')->assertOk();
});

// ── /blog routes ─────────────────────────────────────────────────────────────

it('GET /blog returns 200', function () {
    $this->get('/blog')->assertOk();
});

it('/blog page contains Blog heading', function () {
    $html = $this->get('/blog')->assertOk()->getContent();
    expect($html)->toContain('Blog');
});

it('/blog page includes canonical link', function () {
    $html = $this->get('/blog')->assertOk()->getContent();
    expect($html)->toContain('rel="canonical"');
});

it('/blog/:slug returns 404 for non-existent post', function () {
    $this->get('/blog/this-post-does-not-exist-xyz')->assertNotFound();
});

it('published blog post is accessible at /blog/:slug', function () {
    $post = \App\Models\BlogPost::factory()->create([
        'slug'         => 'hello-world',
        'title'        => 'Hello World Post',
        'body'         => '<p>Test content.</p>',
        'is_published' => true,
        'published_at' => now()->subDay(),
    ]);

    $html = $this->get('/blog/hello-world')->assertOk()->getContent();
    expect($html)->toContain('Hello World Post');
});

it('unpublished blog post returns 404', function () {
    \App\Models\BlogPost::factory()->create([
        'slug'         => 'draft-post',
        'title'        => 'Draft Post',
        'body'         => '<p>Draft.</p>',
        'is_published' => false,
    ]);

    $this->get('/blog/draft-post')->assertNotFound();
});

it('/blog post includes Article JSON-LD', function () {
    \App\Models\BlogPost::factory()->create([
        'slug'         => 'schema-post',
        'title'        => 'Schema Post',
        'body'         => '<p>Content.</p>',
        'is_published' => true,
        'published_at' => now()->subHour(),
    ]);

    $html = $this->get('/blog/schema-post')->assertOk()->getContent();
    expect($html)->toContain('"Article"');
});

// ── /pages routes ─────────────────────────────────────────────────────────────

it('GET /pages/:slug returns 404 for non-existent page', function () {
    $this->get('/pages/does-not-exist-xyz')->assertNotFound();
});

it('published page is accessible at /pages/:slug', function () {
    \App\Models\Page::factory()->create([
        'slug'         => 'test-page',
        'title'        => 'Test Page Title',
        'body'         => '<p>Page content.</p>',
        'is_published' => true,
        'published_at' => now()->subDay(),
    ]);

    $html = $this->get('/pages/test-page')->assertOk()->getContent();
    expect($html)->toContain('Test Page Title');
});

it('/about returns 200 when about page exists', function () {
    \App\Models\Page::factory()->create([
        'slug'         => 'about',
        'title'        => 'About Skinbase',
        'body'         => '<p>About us.</p>',
        'is_published' => true,
        'published_at' => now()->subDay(),
    ]);

    $this->get('/about')->assertOk();
});

it('/legal/terms returns 200 when legal-terms page exists', function () {
    \App\Models\Page::factory()->create([
        'slug'         => 'legal-terms',
        'title'        => 'Terms of Service',
        'body'         => '<p>Terms.</p>',
        'is_published' => true,
        'published_at' => now()->subDay(),
    ]);

    $this->get('/legal/terms')->assertOk();
});

// ── tags index layout ─────────────────────────────────────────────────────────

it('/tags page renders with ContentLayout breadcrumbs', function () {
    $html = $this->get('/tags')->assertOk()->getContent();
    // ContentLayout should inject breadcrumb nav
    expect($html)->toContain('Tags');
});

it('/tags page includes canonical and robots', function () {
    $html = $this->get('/tags')->assertOk()->getContent();
    expect($html)
        ->toContain('rel="canonical"')
        ->toContain('index,follow');
});
