<?php

namespace App\Livewire\Portal\Concerns;

use App\Domain\Shared\Context\PortalContext;

/**
 * What every portal screen shares: it authorises in mount(), and it reads its
 * scope from PortalContext rather than from a route parameter or a public
 * property.
 *
 * The `#[Locked]` distinction is not optional here. This project runs Livewire
 * v4, where a plain `public` property is settable from the browser — so
 * validating an id in mount() and then filtering queries on it in render() is
 * an IDOR, not a check. Nothing in this namespace holds a participant id in a
 * public property at all: the active member comes from the session through
 * PortalContext, which re-validates it against GuardianResolver on every read.
 */
trait PortalScreen
{
    protected function portal(): PortalContext
    {
        return app(PortalContext::class);
    }

    /**
     * Gate the screen. Called from every mount().
     *
     * Two separate questions, and both have to be asked: does this account hold
     * the permission, and does it speak for anybody at all. A staff account
     * with portal.access but no children must not land in an empty portal
     * pretending to be a member.
     */
    protected function authorizePortal(?string $permission = null): void
    {
        $this->authorize($permission ?? 'portal.access');

        if (! $this->portal()->speaksForAnyone()) {
            abort(403, __('هذا الحساب غير مرتبط بأي عضو في الأكاديمية'));
        }
    }

    /** The member a member-scoped surface is showing. */
    protected function activeParticipantId(): int
    {
        $id = $this->portal()->participantId();

        abort_if($id === null, 403, __('هذا الحساب غير مرتبط بأي عضو في الأكاديمية'));

        return $id;
    }

    /**
     * Every participant this account speaks for.
     *
     * Money is family-scoped and training is member-scoped — that split is the
     * switcher's whole meaning, and it is decided here rather than eleven times
     * over.
     *
     * @return array<int, int>
     */
    protected function familyParticipantIds(): array
    {
        return $this->portal()->moneyParticipantIds();
    }
}
