<?php

namespace Tests\Feature;

use App\Livewire\System\Index;
use App\Models\User;
use App\Services\DeploymentService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
use Tests\TestCase;

/**
 * The restart sentinel: the dashboard writes a marker file (DeploymentService) that a
 * HOST-side watcher reacts to and restarts the stack. The container never gets the
 * Docker socket. These tests exercise the file lifecycle + the one-click Livewire flow,
 * and always clean the sentinel up afterwards (it lives on a real storage path).
 */
class RestartSentinelTest extends TestCase
{
    use RefreshDatabase;

    private function sentinelPath(): string
    {
        return app(DeploymentService::class)->restartSignalPath();
    }

    private function removeSentinel(): void
    {
        $path = $this->sentinelPath();
        if (is_file($path)) {
            @unlink($path);
        }
    }

    protected function setUp(): void
    {
        parent::setUp();
        $this->removeSentinel(); // never inherit a stray sentinel from a prior run
    }

    protected function tearDown(): void
    {
        $this->removeSentinel(); // leave the storage dir as we found it
        parent::tearDown();
    }

    public function test_request_restart_creates_the_sentinel_and_request_reports_it(): void
    {
        $deployment = app(DeploymentService::class);

        $this->assertFalse($deployment->restartRequested(), 'no sentinel before requesting');

        $deployment->requestRestart();

        $this->assertTrue(is_file($this->sentinelPath()), 'sentinel file exists on disk');
        $this->assertTrue($deployment->restartRequested(), 'restartRequested() reflects the file');
        $this->assertNotSame('', trim((string) file_get_contents($this->sentinelPath())), 'sentinel carries a marker');
    }

    public function test_clear_restart_request_removes_the_sentinel(): void
    {
        $deployment = app(DeploymentService::class);

        $deployment->requestRestart();
        $this->assertTrue($deployment->restartRequested());

        $deployment->clearRestartRequest();
        $this->assertFalse($deployment->restartRequested(), 'sentinel is gone after clearing');
    }

    public function test_restart_now_writes_the_sentinel_and_sets_the_flag(): void
    {
        $this->actingAs(User::factory()->create(['must_change_password' => false]));

        Livewire::test(Index::class)
            ->call('restartNow', app(DeploymentService::class))
            ->assertSet('restartRequested', true);

        $this->assertTrue(
            app(DeploymentService::class)->restartRequested(),
            'the one-click action persisted the sentinel a host watcher will see',
        );
    }
}
