<?php

use App\Models\ContentType;
use App\Models\User;
use App\Services\ArtworkService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\DB;

uses(RefreshDatabase::class);

function toolbarEmptyPaginator(string $path = '/'): LengthAwarePaginator
{
    return (new LengthAwarePaginator(collect(), 0, 20, 1))->setPath($path);
}

beforeEach(function () {
    $this->artworksMock = \Mockery::mock(ArtworkService::class);
    $this->artworksMock->shouldReceive('getFeaturedArtworks')->andReturn(toolbarEmptyPaginator('/'))->byDefault();
    $this->artworksMock->shouldReceive('getFeaturedArtworkWinner')->andReturn(null)->byDefault();
    $this->artworksMock->shouldReceive('getLatestArtworks')->andReturn(collect())->byDefault();
    $this->app->instance(ArtworkService::class, $this->artworksMock);
});

function exploreMenuItems(string $html): array
{
    $document = new DOMDocument();
    @$document->loadHTML($html);

    $xpath = new DOMXPath($document);
    $nodes = $xpath->query('//div[@id="dd-browse"]/a');

    $items = [];

    foreach ($nodes as $node) {
        $items[] = [
            'href' => (string) $node->attributes->getNamedItem('href')?->nodeValue,
            'label' => trim(preg_replace('/\s+/', ' ', $node->textContent ?? '') ?? ''),
        ];
    }

    return $items;
}

it('orders explore menu content types from the database and appends categories and tags', function () {
    DB::table('content_types')->insert([
        ['name' => 'Wallpapers', 'slug' => 'wallpapers', 'description' => null, 'order' => 2],
        ['name' => 'Digital Art', 'slug' => 'digital-art', 'description' => null, 'order' => 1],
        ['name' => 'Photography', 'slug' => 'photography', 'description' => null, 'order' => 3],
    ]);

    $items = exploreMenuItems($this->get('/')->assertOk()->getContent());

    expect(array_map(fn (array $item) => $item['label'], $items))->toBe([
        'All Artworks',
        'Digital Art',
        'Wallpapers',
        'Photography',
        'Categories',
        'Tags',
    ]);

    expect(array_map(fn (array $item) => $item['href'], $items))->toBe([
        '/explore',
        '/digital-art',
        '/wallpapers',
        '/photography',
        route('categories.index'),
        '/tags',
    ]);
});

it('reflects updated content type ordering on the next request', function () {
    DB::table('content_types')->insert([
        ['name' => 'Wallpapers', 'slug' => 'wallpapers', 'description' => null, 'order' => 1],
        ['name' => 'Digital Art', 'slug' => 'digital-art', 'description' => null, 'order' => 2],
    ]);

    $initialItems = exploreMenuItems($this->get('/')->assertOk()->getContent());

    expect(array_map(fn (array $item) => $item['label'], $initialItems))->toBe([
        'All Artworks',
        'Wallpapers',
        'Digital Art',
        'Categories',
        'Tags',
    ]);

    ContentType::query()->where('slug', 'digital-art')->firstOrFail()->update(['order' => 1]);
    ContentType::query()->where('slug', 'wallpapers')->firstOrFail()->update(['order' => 2]);

    $updatedItems = exploreMenuItems($this->get('/')->assertOk()->getContent());

    expect(array_map(fn (array $item) => $item['label'], $updatedItems))->toBe([
        'All Artworks',
        'Digital Art',
        'Wallpapers',
        'Categories',
        'Tags',
    ]);
});

it('omits content types marked hidden from the explore menu', function () {
    DB::table('content_types')->insert([
        ['name' => 'Wallpapers', 'slug' => 'wallpapers', 'description' => null, 'order' => 1, 'hide_from_menu' => false],
        ['name' => 'Private Type', 'slug' => 'private-type', 'description' => null, 'order' => 2, 'hide_from_menu' => true],
        ['name' => 'Photography', 'slug' => 'photography', 'description' => null, 'order' => 3, 'hide_from_menu' => false],
    ]);

    $items = exploreMenuItems($this->get('/')->assertOk()->getContent());

    expect(array_map(fn (array $item) => $item['label'], $items))->toBe([
        'All Artworks',
        'Wallpapers',
        'Photography',
        'Categories',
        'Tags',
    ]);

    expect(array_map(fn (array $item) => $item['href'], $items))->not->toContain('/private-type');
});

it('shows a verification reminder in the toolbar for unverified users', function () {
    $user = User::factory()->unverified()->create();

    $response = $this->actingAs($user)->get('/');

    $response
        ->assertOk()
        ->assertSee('Verify email')
        ->assertSee('Verify your email')
        ->assertSee($user->email)
        ->assertSee('/verify-email', false)
        ->assertSee('/email/verification-notification', false)
        ->assertSee('Resend verification email');
});

it('shows resend success feedback in the toolbar reminder after sending a verification email', function () {
    $user = User::factory()->unverified()->create();

    $response = $this
        ->actingAs($user)
        ->withSession(['status' => 'verification-link-sent'])
        ->get('/');

    $response
        ->assertOk()
        ->assertSee('A fresh verification link was sent to your email.');
});

it('hides the verification reminder for verified users', function () {
    $user = User::factory()->create();

    $response = $this->actingAs($user)->get('/');

    $response
        ->assertOk()
        ->assertDontSee('Verify your email')
        ->assertDontSee('Resend verification email');
});
