<?php

namespace App\Domain\Shared\Traits;

use App\Domain\Shared\Context\BranchContext;

/**
 * Read the active branch inside a Livewire component.
 *
 * All three methods delegate to BranchContext, which owns the session-state
 * rules. The signatures are unchanged, so the 80-odd components using this
 * trait need no edits.
 */
trait UsesBranchScope
{
    protected function branchContext(): BranchContext
    {
        return app(BranchContext::class);
    }

    /**
     * The branch to filter by, or null for "every branch".
     *
     * Null is a real answer, not a missing one — pass it straight into the
     * `->when($branchId, ...)` idiom used across the app.
     */
    public function getActiveBranchId(): ?int
    {
        return $this->branchContext()->branchId();
    }

    /**
     * Alias with a name that says what it is actually for.
     */
    public function getBranchIdForQuery(): ?int
    {
        return $this->getActiveBranchId();
    }

    /**
     * For screens that cannot work across branches — a cash drawer, a till, a
     * registration desk.
     *
     * This used to quietly write a branch into the session when none was set,
     * which would unlock a user who was deliberately viewing every branch.
     * It now refuses instead.
     */
    public function getActiveBranchIdOrFail(): int
    {
        return $this->branchContext()->requireBranchId();
    }

    public function isAllBranches(): bool
    {
        return $this->branchContext()->isAllBranches();
    }

    /**
     * The branches this component may offer in a picker.
     *
     * Almost every screen wants exactly one entry — the branch you are in —
     * because a per-screen branch filter alongside the topbar switcher is two
     * controls for one piece of state, and the second one was how another
     * branch's rows kept reaching screens that had otherwise been filtered
     * correctly. Only a user genuinely in all-branches mode gets a list.
     */
    public function selectableBranches(): \Illuminate\Support\Collection
    {
        $context = $this->branchContext();

        if ($context->isAllBranches()) {
            return $context->activeBranches();
        }

        $current = $context->currentBranch();

        return $current ? collect([$current]) : collect();
    }

    /**
     * Run a query with branch enforcement lifted.
     *
     * For the few screens that are cross-branch by definition — transferring a
     * player to another branch, an executive roll-up. Every call is a hole in
     * the isolation the rest of the app now relies on, so it should be obvious
     * in the diff.
     */
    protected function acrossBranches(callable $callback): mixed
    {
        return app(\App\Domain\Shared\Context\BranchScopeState::class)
            ->withoutScope($callback);
    }
}
