<?php

use App\Models\Booking;
use App\Models\Floor;
use App\Models\User;
use Database\Seeders\PermissionSeeder;
use Database\Seeders\RoleSeeder;
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;

uses(LazilyRefreshDatabase::class);

beforeEach(function () {
    $this->withHeaders([
        'Origin' => 'http://localhost:3000',
        'Referer' => 'http://localhost:3000/',
    ]);

    $this->seed([
        PermissionSeeder::class,
        RoleSeeder::class,
    ]);
});

it('lists floors for users with units.view', function () {
    $manager = User::factory()->manager()->create();
    $floor = Floor::factory()->for($manager, 'creator')->create([
        'name' => 'Ground',
        'sort_order' => 0,
    ]);

    $this->actingAs($manager)
        ->getJson('/api/floors')
        ->assertSuccessful()
        ->assertJsonCount(1, 'data')
        ->assertJsonPath('data.0.id', $floor->id)
        ->assertJsonPath('data.0.name', 'Ground')
        ->assertJsonPath('data.0.sortOrder', 0);
});

it('creates a floor as an admin', function () {
    $admin = User::factory()->admin()->create();

    $this->actingAs($admin)
        ->postJson('/api/floors', [
            'name' => 'Mezzanine',
            'sort_order' => 1,
        ])
        ->assertCreated()
        ->assertJsonPath('data.name', 'Mezzanine')
        ->assertJsonPath('data.sortOrder', 1)
        ->assertJsonPath('data.createdBy.id', $admin->id);
});

it('forbids managers from creating floors', function () {
    $manager = User::factory()->manager()->create();

    $this->actingAs($manager)
        ->postJson('/api/floors', [
            'name' => 'Ground',
        ])
        ->assertForbidden();
});

it('updates a floor', function () {
    $admin = User::factory()->admin()->create();
    $floor = Floor::factory()->for($admin, 'creator')->create(['name' => '1']);

    $this->actingAs($admin)
        ->patchJson("/api/floors/{$floor->id}", [
            'name' => 'First',
            'sort_order' => 1,
        ])
        ->assertSuccessful()
        ->assertJsonPath('data.name', 'First')
        ->assertJsonPath('data.sortOrder', 1);
});

it('deletes a floor with no bookings', function () {
    $admin = User::factory()->admin()->create();
    $floor = Floor::factory()->for($admin, 'creator')->create();

    $this->actingAs($admin)
        ->deleteJson("/api/floors/{$floor->id}")
        ->assertNoContent();

    $this->assertModelMissing($floor);
});

it('does not delete a floor that has bookings', function () {
    $admin = User::factory()->admin()->create();
    $booking = Booking::factory()->for($admin, 'creator')->create();

    $this->actingAs($admin)
        ->deleteJson("/api/floors/{$booking->floor_id}")
        ->assertUnprocessable()
        ->assertJsonValidationErrors(['floor']);
});

it('does not let guests view floors', function () {
    $this->getJson('/api/floors')->assertUnauthorized();
});
