<?php

namespace App\Services\Care;

use App\Models\Branch;
use App\Models\Member;
use App\Models\Organization;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;

/**
 * Resolves which Care branch the current user is working in.
 *
 * Doctors may be assigned to multiple sites (telemedicine) but only those
 * explicitly linked on their practitioner desks — never org-wide by default.
 * Hospital admins pick among all branches; that choice is remembered in session.
 */
class BranchContext
{
    public const SESSION_KEY = 'care.preferred_branch_id';

    public function __construct(
        protected OrganizationResolver $organizations,
    ) {}

    public function canSwitch(?Member $member): bool
    {
        if ($member === null) {
            return false;
        }

        if ($member->role === 'doctor' || app(CarePermissions::class)->usesPractitionerBranchScope($member)) {
            return count($this->organizations->doctorAssignedBranchIds($member)) > 1;
        }

        // Other site clinicians stay on their assigned branch — never a picker.
        if (in_array($member->role, app(CarePermissions::class)->floorCareRoles(), true)
            && ! app(CarePermissions::class)->usesPractitionerBranchScope($member)) {
            return false;
        }

        return $this->organizations->allowedBranchIds($member) === null;
    }

    /**
     * Active branches the member may see.
     *
     * @return Collection<int, Branch>
     */
    public function branches(Request $request, Organization $organization, ?Member $member): Collection
    {
        $ids = $this->organizations->allowedBranchIds($member);

        return Branch::owned((string) $organization->owner_ref)
            ->where('organization_id', $organization->id)
            ->where('is_active', true)
            ->when($ids !== null, fn ($q) => $q->whereIn('id', $ids !== [] ? $ids : [0]))
            ->orderBy('name')
            ->get();
    }

    /**
     * Preferred working branch id (0 when none allowed).
     * Persists switcher selections from ?branch_id= into the session.
     */
    public function resolve(Request $request, Organization $organization, ?Member $member): int
    {
        $branches = $this->branches($request, $organization, $member);
        $allowed = $branches->pluck('id')->map(fn ($id) => (int) $id)->all();
        if ($allowed === []) {
            return 0;
        }

        if ($this->canSwitch($member)) {
            if ($request->filled('branch_id')) {
                $requested = (int) $request->input('branch_id');
                if (in_array($requested, $allowed, true)) {
                    $request->session()->put(self::SESSION_KEY, $requested);

                    return $requested;
                }
            }

            $preferred = (int) $request->session()->get(self::SESSION_KEY, 0);
            if ($preferred > 0 && in_array($preferred, $allowed, true)) {
                return $preferred;
            }

            $fallback = (int) $branches->first()->id;
            $request->session()->put(self::SESSION_KEY, $fallback);

            return $fallback;
        }

        return (int) $allowed[0];
    }
}
