<?php

declare(strict_types=1);

use App\Enums\Auth\CrudPermission;
use App\Events\List\Playlist\PlaylistCreated;
use App\Features\AllowPlaylistManagement;
use App\Models\Auth\User;
use App\Models\List\Playlist;
use Illuminate\Support\Facades\Event;
use Laravel\Pennant\Feature;

use function Pest\Laravel\actingAs;

beforeEach(function (): void {
    $this->mutation = '
        mutation($id: String!, $name: String, $visibility: PlaylistVisibility, $description: String) {
            UpdatePlaylist(id: $id, name: $name, visibility: $visibility, description: $description) {
                name
                visibility
                description
            }
        }
    ';
});

test('protected', function (): void {
    $response = $this->graphQL(
        $this->mutation,
        [
            'id' => fake()->word(),
        ],
    );

    $response->assertOk();
    $response->assertJsonPath('errors.0.message', 'This action is unauthorized.');
});

test('forbidden', function (): void {
    Event::fakeExcept(PlaylistCreated::class);

    actingAs(User::factory()->createOne());

    $response = $this->graphQL(
        $this->mutation,
        [
            // Needed for the bind resolver.
            'id' => Playlist::factory()->createOne()->hashid,
        ],
    );

    $response->assertOk();
    $response->assertJsonPath('errors.0.message', 'This action is unauthorized.');
});

test('forbidden if feature flag is disabled', function (): void {
    Feature::deactivate(AllowPlaylistManagement::class);

    Event::fakeExcept(PlaylistCreated::class);

    $user = User::factory()
        ->withPermissions(CrudPermission::DELETE->format(Playlist::class))
        ->createOne();

    actingAs($user);

    $response = $this->graphQL(
        $this->mutation,
        [
            // Needed for the bind resolver.
            'id' => Playlist::factory()->createOne()->hashid,
        ],
    );

    $response->assertOk();
    $response->assertJsonPath('errors.0.message', 'This action is unauthorized.');
});

test('forbidden if not owner', function (): void {
    Feature::activate(AllowPlaylistManagement::class);

    Event::fakeExcept(PlaylistCreated::class);

    $user = User::factory()
        ->withPermissions(CrudPermission::UPDATE->format(Playlist::class))
        ->createOne();

    actingAs($user);

    $response = $this->graphQL(
        $this->mutation,
        [
            'id' => Playlist::factory()->createOne()->hashid,
        ],
    );

    $response->assertOk();
    $response->assertJsonPath('errors.0.message', 'This action is unauthorized.');
});

it('updates', function (): void {
    Feature::activate(AllowPlaylistManagement::class);

    Event::fakeExcept(PlaylistCreated::class);

    $user = User::factory()
        ->withPermissions(CrudPermission::UPDATE->format(Playlist::class))
        ->createOne();

    actingAs($user);

    $playlist = Playlist::factory()
        ->for($user)
        ->createOne();

    $newPlaylist = Playlist::factory()->makeOne();

    $response = $this->graphQL(
        $this->mutation,
        [
            'id' => $playlist->hashid,
            'name' => $newPlaylist->name,
            'visibility' => $newPlaylist->visibility->name,
            'description' => $newPlaylist->description,
        ],
    );

    $response->assertOk();
    $response->assertJson([
        'data' => [
            'UpdatePlaylist' => [
                'name' => $newPlaylist->name,
                'visibility' => $newPlaylist->visibility->name,
                'description' => $newPlaylist->description,
            ],
        ],
    ]);
});
