<?php

namespace Tests\Feature;

use App\Livewire\Modals\SshKeyProvision;
use App\Models\Server;
use App\Models\User;
use App\Services\SshKeyProvisioner;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
use Mockery;
use Tests\TestCase;

class SshKeyProvisionModalTest extends TestCase
{
    use RefreshDatabase;

    protected function tearDown(): void
    {
        Mockery::close();
        parent::tearDown();
    }

    public function test_run_reveals_the_key_and_signals_a_reload_on_success(): void
    {
        $this->actingAs(User::factory()->create());
        $server = Server::create(['name' => 'box', 'ip' => '10.0.0.9', 'ssh_port' => 22, 'status' => 'online']);

        $svc = Mockery::mock(SshKeyProvisioner::class);
        $svc->shouldReceive('enableKeyOnlyAccess')->once()
            ->andReturn(['ok' => true, 'privateKey' => 'PRIVATE-PEM', 'publicKey' => 'ssh-ed25519 AAAA']);
        app()->instance(SshKeyProvisioner::class, $svc);

        Livewire::test(SshKeyProvision::class, ['serverId' => $server->id])
            ->call('run')
            ->assertSet('done', true)
            ->assertSet('ok', true)
            ->assertSet('privateKey', 'PRIVATE-PEM')
            ->assertDispatched('hardeningApplied')
            ->assertSee('PRIVATE-PEM');
    }

    public function test_run_surfaces_an_error_without_revealing_a_key(): void
    {
        $this->actingAs(User::factory()->create());
        $server = Server::create(['name' => 'box', 'ip' => '10.0.0.9', 'ssh_port' => 22, 'status' => 'online']);

        $svc = Mockery::mock(SshKeyProvisioner::class);
        $svc->shouldReceive('enableKeyOnlyAccess')->once()
            ->andReturn(['ok' => false, 'error' => 'verify failed']);
        app()->instance(SshKeyProvisioner::class, $svc);

        Livewire::test(SshKeyProvision::class, ['serverId' => $server->id])
            ->call('run')
            ->assertSet('done', true)
            ->assertSet('ok', false)
            ->assertSet('privateKey', null)
            ->assertSee('verify failed');
    }

    public function test_run_surfaces_a_thrown_service_exception_as_an_error(): void
    {
        $this->actingAs(User::factory()->create());
        $server = Server::create(['name' => 'box', 'ip' => '10.0.0.9', 'ssh_port' => 22, 'status' => 'online']);

        $svc = Mockery::mock(SshKeyProvisioner::class);
        $svc->shouldReceive('enableKeyOnlyAccess')->once()->andThrow(new \RuntimeException('ssh dropped'));
        app()->instance(SshKeyProvisioner::class, $svc);

        Livewire::test(SshKeyProvision::class, ['serverId' => $server->id])
            ->call('run')
            ->assertSet('done', true)
            ->assertSet('ok', false)
            ->assertSet('privateKey', null)
            ->assertSee('ssh dropped');
    }
}
