<?php

declare(strict_types=1);

namespace App\Models;

use App\Enums\TransferStatus;
use App\Services\BranchAccessService;
use Database\Factories\MemberTransferFactory;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class MemberTransfer extends Model
{
    /** @use HasFactory<MemberTransferFactory> */
    use HasFactory;

    protected $fillable = [
        'member_id',
        'from_branch_id',
        'to_branch_id',
        'status',
        'reason',
        'requested_by',
        'decided_by',
        'decided_at',
    ];

    protected function casts(): array
    {
        return [
            'status' => TransferStatus::class,
            'decided_at' => 'datetime',
        ];
    }

    public function member(): BelongsTo
    {
        return $this->belongsTo(Member::class);
    }

    public function fromBranch(): BelongsTo
    {
        return $this->belongsTo(Branch::class, 'from_branch_id');
    }

    public function toBranch(): BelongsTo
    {
        return $this->belongsTo(Branch::class, 'to_branch_id');
    }

    public function requestedBy(): BelongsTo
    {
        return $this->belongsTo(User::class, 'requested_by');
    }

    public function decidedBy(): BelongsTo
    {
        return $this->belongsTo(User::class, 'decided_by');
    }

    /**
     * Visible if either side of the transfer touches the user's accessible
     * branches — never leak existence of transfers wholly outside scope.
     */
    public function scopeVisibleTo(Builder $query, User $user): Builder
    {
        $branchIds = app(BranchAccessService::class)->accessibleBranchIds($user);

        if ($branchIds === null) {
            return $query;
        }

        return $query->where(
            fn (Builder $q) => $q->whereIn('from_branch_id', $branchIds)->orWhereIn('to_branch_id', $branchIds),
        );
    }

    /**
     * Cross-branch reads must 404, not 403 — see Member::resolveRouteBinding.
     */
    public function resolveRouteBinding($value, $field = null)
    {
        $query = static::query();
        $user = auth()->user();

        if ($user) {
            $query->visibleTo($user);
        }

        return $query->where($field ?? $this->getRouteKeyName(), $value)->first();
    }
}
