<?php

namespace App\Livewire\Concerns;

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

/**
 * The one place a console Livewire component resolves "who is signed in"
 * and decides what happens when the answer is nobody.
 *
 * A Livewire action reaches its component through its own request to
 * /livewire/update, separate from the request that first rendered the page —
 * a modal especially, reachable without the page's own route middleware (see
 * R20 in CLAUDE.md). An operator whose session has ended by the time an
 * action runs still reaches this code, and Auth::guard('operator')->user()
 * comes back null. Four components each dereferenced it unguarded
 * ($operator->password, ->id, ->two_factor_recovery_codes, …), turning that
 * into a 500 instead of a sign-in prompt.
 *
 * currentOperator() cannot throw its way out of the null case. Livewire only
 * turns $this->redirect() into a browser navigation once the calling action
 * returns NORMALLY: the redirect is queued as component state and picked up
 * during Livewire's own dehydrate step (Livewire\Features\SupportRedirects),
 * which runs strictly after the called method returns — an uncaught
 * exception during the call skips it entirely and Livewire ships back a bare
 * error response instead (confirmed by reading
 * Livewire\Mechanisms\HandleComponents::update() and
 * Livewire\Mechanisms\HandleRequests::handleUpdate(), which catches nothing
 * but \TypeError). So this returns null and every caller checks for it:
 *
 *     if (! $operator = $this->currentOperator()) {
 *         return;
 *     }
 *
 * That one-line guard is the only thing left for a caller to get wrong; the
 * redirect target and the mechanism live here once, so the four cannot drift
 * apart the way the original unguarded dereferences did.
 */
trait ResolvesOperator
{
    protected function currentOperator(): ?Operator
    {
        $operator = Auth::guard('operator')->user();

        if ($operator === null) {
            $this->redirect(route('admin.login'));
        }

        return $operator;
    }
}
