<?php

use App\Models\Operator;
use App\Models\User;
use Illuminate\Support\Facades\Auth;

/**
 * routes/channels.php's admin.runs channel — the console's live provisioning
 * feed. Its own callback checks Auth::guard('operator') correctly, but that
 * is not what this file is about: it is about whether the callback ever runs
 * at all.
 *
 * BROADCAST_CONNECTION=null (this suite's forced default, phpunit.xml) backs
 * onto NullBroadcaster, whose auth() is a bare no-op — it never calls a
 * channel's own callback, so it cannot exercise this bug or its fix either
 * way. A real Pusher-protocol broadcaster (Reverb uses PusherBroadcaster
 * under the hood, BroadcastManager::createReverbDriver()) is switched in
 * instead, via config rather than a container binding: Broadcast::auth()
 * resolves through BroadcastManager::__call() -> driver(), which reads
 * config('broadcasting.default') and builds its OWN instance — a container
 * binding for BroadcasterContract is a separate, unrelated seam that
 * driver() never consults. No live Reverb server is needed: auth() is pure
 * PHP — channel authorization is an HMAC signature computed locally, never a
 * call over the network.
 */
function bindRealBroadcaster(): void
{
    config()->set('broadcasting.default', 'reverb');
    config()->set('broadcasting.connections.reverb.key', 'test-key');
    config()->set('broadcasting.connections.reverb.secret', 'test-secret');
    config()->set('broadcasting.connections.reverb.app_id', 'test-app-id');
    config()->set('broadcasting.connections.reverb.options', [
        'host' => '127.0.0.1', 'port' => 6001, 'scheme' => 'http', 'useTLS' => false,
    ]);

    // routes/channels.php ran once already, at boot, registering admin.runs
    // against whichever broadcaster 'null' (this suite's forced default)
    // resolved to at the time. Switching the default config above builds a
    // brand new driver instance on next use — it does not retroactively
    // register anything on it. Re-requiring the routes file does.
    require base_path('routes/channels.php');
}

function authorizeAdminRunsChannel()
{
    return test()->post('/broadcasting/auth', [
        'channel_name' => 'private-admin.runs',
        'socket_id' => '1234.1234',
    ]);
}

it('lets an operator authorize the console live-feed channel on the operator guard', function () {
    bindRealBroadcaster();
    $operator = Operator::factory()->role('Owner')->create();

    $this->actingAs($operator, 'operator');
    // actingAs() also flips Auth's DEFAULT guard to 'operator' (Auth::
    // shouldUse()) — nothing does that for a real request to this route in
    // production (/broadcasting/auth carries only the 'web' middleware
    // group, never auth:operator,web), so left alone this would make the
    // bare/default guard resolve the operator too and mask exactly the bug
    // this test exists to catch. Reset so only the 'operator' GUARD INSTANCE
    // (already given its user by actingAs() above, untouched by shouldUse())
    // has the operator signed in — matching a real session.
    Auth::shouldUse('web');

    authorizeAdminRunsChannel()->assertOk();
});

it('refuses a guest on the console live-feed channel', function () {
    bindRealBroadcaster();

    authorizeAdminRunsChannel()->assertForbidden();
});

it('refuses a signed-in portal customer who is not an operator', function () {
    bindRealBroadcaster();
    $user = User::factory()->create();

    $this->actingAs($user);

    // Signed in on 'web', not 'operator' — retrieveUser() now finds THIS
    // user (guards => ['operator', 'web']) and reaches the channel's own
    // callback, which must still refuse them: they hold no operator role.
    authorizeAdminRunsChannel()->assertForbidden();
});
