<?php

namespace App\Appointment\Availability\Picker;

use App\Resource\Entity\ClinicResource;
use App\Shared\Time\TimeInterval;

/**
 * منبعی که کمترین وقتِ مرده را جا می‌گذارد.
 *
 * اگر اپراتوری از ساعت ۱۰ تا ۱۲ آزاد است و نوبت ۱۰ تا ۱۱ می‌خواهد، یک ساعت خالی
 * می‌ماند؛ اپراتوری که از ۱۰ تا ۱۱ آزاد است هیچ. دومی انتخاب می‌شود تا پنجره‌های
 * بزرگ‌تر برای نوبت‌های طولانی‌تر باقی بمانند.
 *
 * این همان چیزی است که «تکه‌تکه شدن تقویم» را کم می‌کند — بدون آن، هر رزرو یک شکاف
 * غیرقابل‌فروش وسط روز باز می‌کند.
 */
final class LeastGapPicker implements ResourcePicker
{
    public static function code(): string { return 'least_gap'; }

    public static function label(): string { return 'کمترین وقت مرده — تقویم کمتر تکه‌تکه می‌شود'; }

    public function order(array $candidates, PickContext $context): array
    {
        $ordered = $candidates;

        usort(
            $ordered,
            fn (ClinicResource $a, ClinicResource $b): int
                => $this->wasteOf($a, $context) <=> $this->wasteOf($b, $context),
        );

        return $ordered;
    }

    /**
     * دقایقی از پنجرهٔ میزبان که بعد از این نوبت هدر می‌رود.
     *
     * منبعی که هیچ پنجرهٔ پوشش‌دهنده‌ای ندارد بزرگ‌ترین عدد می‌گیرد و ته صف می‌رود —
     * حذفش اینجا کار موتور است نه استراتژی.
     */
    private function wasteOf(ClinicResource $resource, PickContext $context): int
    {
        $windows = $context->freeWindows[(int) $resource->getId()] ?? [];
        $start   = $context->neededStart();
        $end     = $context->neededEnd();

        $best = PHP_INT_MAX;

        foreach ($windows as $window) {
            if ($window->start > $start || $window->end < $end) {
                continue;
            }

            $best = min($best, ($start - $window->start) + ($window->end - $end));
        }

        return $best;
    }
}
