<?php

namespace App\Livewire;

use App\Domain\Shared\Context\BranchContext;
use Livewire\Component;

class BranchSwitcher extends Component
{
    public string $selectedBranch = 'all';
    public bool $isPinned = false;

    /** Whether to offer the "كل الفروع" option at all. */
    public bool $canViewAll = false;

    /**
     * Purely a reader. Seeding the session is ResolveBranchContext's job now —
     * doing it here meant this method overwrote the "all branches" null with a
     * concrete branch on every render, so that mode could never be held.
     */
    public function mount(): void
    {
        $ctx = app(BranchContext::class);

        $this->isPinned = auth()->user()->preferred_branch_id !== null;
        $this->canViewAll = $ctx->canViewAllBranches();

        $branchId = $ctx->branchId();
        $this->selectedBranch = $branchId === null ? 'all' : (string) $branchId;
    }

    public function updatedSelectedBranch($value): void
    {
        $ctx = app(BranchContext::class);
        $user = auth()->user();

        if ($value === 'all') {
            // Offered only to users who may actually see every branch; guard
            // anyway so a crafted request cannot strand someone in a mode the
            // context would immediately repair.
            if (! $ctx->canViewAllBranches()) {
                return;
            }

            $ctx->set(null);
            $user->update(['preferred_branch_id' => null]);
            $this->isPinned = false;

            $target = route($ctx->redirectRouteName());
        } else {
            $branchId = $this->branchIdFromSelection($value, $ctx);

            // The session value this writes is what BranchScope enforces on
            // every model, so an id the dropdown never offered — another
            // academy's branch, a soft-deleted or deactivated one — must not
            // reach it. Restore the current selection instead of setting it.
            if ($branchId === null) {
                $this->selectedBranch = $ctx->branchId() === null
                    ? 'all'
                    : (string) $ctx->branchId();

                return;
            }

            $ctx->set($branchId);
            $user->update(['preferred_branch_id' => $branchId]);
            $this->isPinned = true;

            $target = route('dashboard');
        }

        // Route on the new state rather than bouncing back via Referer — the
        // page they came from may no longer be reachable in the mode they just
        // entered.
        $this->redirect($target, navigate: true);
    }

    public function unpin(): void
    {
        auth()->user()->update(['preferred_branch_id' => null]);
        $this->isPinned = false;
    }

    public function pin(): void
    {
        $branchId = $this->branchIdFromSelection($this->selectedBranch, app(BranchContext::class));

        if ($branchId === null) {
            return;
        }

        auth()->user()->update(['preferred_branch_id' => $branchId]);
        $this->isPinned = true;
    }

    /**
     * The branch behind a submitted value, or null when it is not one this
     * dropdown offered.
     *
     * $selectedBranch is bound to the picker, so it arrives from the browser on
     * every round trip and cannot be #[Locked]. Validating it against the same
     * list render() shows is what keeps the switcher from being a "set my
     * branch to any id" endpoint now that the whole application — every global
     * scope included — trusts the value it writes into the session.
     */
    private function branchIdFromSelection(mixed $value, BranchContext $ctx): ?int
    {
        if ($value === null || $value === '' || $value === 'all') {
            return null;
        }

        $branchId = (int) $value;

        return $ctx->activeBranches()->contains('id', $branchId) ? $branchId : null;
    }

    public function render()
    {
        $ctx = app(BranchContext::class);

        return view('livewire.branch-switcher', [
            // Already loaded and cached for this request by the context.
            'branches' => $ctx->activeBranches(),
            'isLocked' => $ctx->isLocked(),
        ]);
    }
}
