<?php

use App\Livewire\Admin\ConfirmDeleteIncident;
use App\Livewire\Admin\Incidents as IncidentConsole;
use App\Models\Incident;
use Livewire\Livewire;

/**
 * Taking a whole incident back.
 *
 * Deliberately a different act from editing an update, which there is still no
 * way to do: an update is a statement made at a time, and rewriting one
 * afterwards is what the record exists to prevent. Removing the WHOLE incident
 * is how a test entry, or one published against the wrong service, is undone —
 * and it leaves nothing half-standing behind.
 */
function anIncident(array $attributes = []): Incident
{
    $incident = Incident::query()->create([
        'title' => 'Testeintrag',
        'impact' => 'degraded',
        'components' => ['portal'],
        'started_at' => now()->subHour(),
        'published_at' => now()->subHour(),
        ...$attributes,
    ]);

    $incident->updates()->create(['status' => 'investigating', 'body' => 'Wird untersucht.']);

    return $incident;
}

it('removes the incident and every entry under it', function () {
    $incident = anIncident();

    Livewire::actingAs(operator('Owner'), 'operator')
        ->test(IncidentConsole::class)
        ->call('delete', $incident->uuid);

    expect(Incident::query()->count())->toBe(0)
        // The updates go with it. A timeline whose incident is gone is rows
        // nobody can reach and nobody will remember to clean up.
        ->and(DB::table('incident_updates')->count())->toBe(0);
});

it('takes it off the public page at once', function () {
    $incident = anIncident(['resolved_at' => now()]);

    $this->get('/status')->assertSee('Testeintrag');

    Livewire::actingAs(operator('Owner'), 'operator')
        ->test(IncidentConsole::class)
        ->call('delete', $incident->uuid);

    $this->get('/status')->assertDontSee('Testeintrag');
});

it('asks first, in the product’s own dialog', function () {
    // R23: not window.confirm. The modal mutates nothing itself — it dispatches
    // to the page component, which is where the capability check already is.
    $incident = anIncident();

    Livewire::actingAs(operator('Owner'), 'operator')
        ->test(ConfirmDeleteIncident::class, ['uuid' => $incident->uuid])
        ->assertSee($incident->title)
        ->call('confirm')
        ->assertDispatched('incident-delete-confirmed');

    // The modal alone does not delete anything.
    expect(Incident::query()->count())->toBe(1);
});

it('needs the capability, not merely an operator account', function () {
    // Asserted on the page, not on the action: render() authorizes too, so an
    // operator without the capability never reaches a button — and a
    // Livewire::test() against a component that refuses to render fails with a
    // snapshot error that says nothing about permissions.
    $incident = anIncident();

    $this->actingAs(operator('Support'), 'operator')
        ->get(route('admin.incidents'))
        ->assertForbidden();

    expect(Incident::query()->count())->toBe(1);
});

it('still offers no way to rewrite a single entry', function () {
    // The rule the delete button must not quietly become an exception to.
    expect(method_exists(IncidentConsole::class, 'editUpdate'))->toBeFalse()
        ->and(method_exists(IncidentConsole::class, 'deleteUpdate'))->toBeFalse();
});
