<?php

use App\Models\Mailbox;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Support\Facades\DB;

beforeEach(function () {
    config()->set('admin_access.secrets_key', 'base64:'.base64_encode(random_bytes(32)));
    clearMailboxSeed();
});

it('stores the password encrypted and never in the clear', function () {
    $box = Mailbox::factory()->create(['key' => 'support', 'password' => 'sehr-geheim']);

    $stored = DB::table('mailboxes')->where('id', $box->id)->value('password');

    expect($stored)->not->toContain('sehr-geheim')
        ->and($box->fresh()->password)->toBe('sehr-geheim');
});

it('is keyed to SECRETS_KEY — rotating it makes the password unreadable', function () {
    // The POSITIVE proof, and the one that discriminates.
    $box = Mailbox::factory()->create(['password' => 'geheim']);

    config()->set('admin_access.secrets_key', 'base64:'.base64_encode(random_bytes(32)));

    expect(fn () => $box->fresh()->password)
        ->toThrow(DecryptException::class);
});

it('is NOT keyed to APP_KEY — rotating that leaves mail working', function () {
    $box = Mailbox::factory()->create(['password' => 'bleibt-lesbar']);

    config()->set('app.key', 'base64:'.base64_encode(random_bytes(32)));

    // forgetInstance is what makes this test mean anything — see above.
    app()->forgetInstance('encrypter');

    expect($box->fresh()->password)->toBe('bleibt-lesbar');
});

it('falls back to the address when no separate username is given', function () {
    $box = Mailbox::factory()->create([
        'address' => 'support@clupilot.com',
        'username' => null,
    ]);

    expect($box->smtpUsername())->toBe('support@clupilot.com');
});

// --- Codex R15#4, P1b: isConfigured() must require a password only when the
// mailbox actually authenticates — a trusted relay that needs no login is
// not the same state as one nobody has finished setting up yet.

it('is configured without a stored password when it does not authenticate', function () {
    // ->fresh(), not the in-memory instance create() returns: authenticates
    // needs its own boolean cast for this to mean anything (a raw DB read
    // comes back "0"/"1", not a real PHP bool), the same gap
    // "stores the password encrypted and never in the clear" above guards
    // against for the password column.
    $box = Mailbox::factory()->create(['authenticates' => false, 'password' => null]);

    expect($box->fresh()->isConfigured())->toBeTrue();
});

it('is NOT configured without a stored password when it does authenticate', function () {
    // The control case: the fix must not make isConfigured() stop requiring
    // a password altogether — only when authenticates is explicitly false.
    $box = Mailbox::factory()->create(['authenticates' => true, 'password' => null]);

    expect($box->fresh()->isConfigured())->toBeFalse();
});

it('still requires active and a non-blank address regardless of authenticates', function () {
    // authenticates=false must widen nothing except the password
    // requirement — an inactive or addressless row stays unconfigured.
    $inactive = Mailbox::factory()->create(['authenticates' => false, 'password' => null, 'active' => false]);
    $blank = Mailbox::factory()->make(['authenticates' => false, 'password' => null, 'address' => '']);

    expect($inactive->fresh()->isConfigured())->toBeFalse()
        ->and($blank->isConfigured())->toBeFalse();
});

it('finds a mailbox by its key', function () {
    Mailbox::factory()->create(['key' => 'billing']);

    expect(Mailbox::findByKey('billing'))->not->toBeNull()
        ->and(Mailbox::findByKey('gibtsnicht'))->toBeNull();
});

it('auto-assigns a uuid and routes by it', function () {
    $box = Mailbox::factory()->create();

    expect($box->uuid)->not->toBeNull()
        ->and($box->getRouteKeyName())->toBe('uuid');
});
