<?php

namespace Modules\ClinicCore\Entities\Services;

use Modules\ClinicCore\Entities\Contracts\ClinicSpecialtyDriver;

/**
 * In-memory registry of clinical-specialty drivers.
 *
 * Each structurally-unique specialty plugin (DermatologyClinic, DentalClinic,
 * …) registers its driver from its service provider's boot() method:
 *
 *     SpecialtyDriverRegistry::register(
 *         new \Modules\DermatologyClinic\Entities\Drivers\DermatologySpecialtyDriver()
 *     );
 *
 * ClinicCore resolves the right driver for an appointment/patient by its
 * specialty code (clc_specialties.code). The registry degrades gracefully:
 * a specialty that has only a clc_specialties config row and no plugin simply
 * has no driver, and ClinicCore renders it with the generic engine.
 *
 * Mirrors \Modules\LabCore\Entities\Services\DriverRegistry.
 */
class SpecialtyDriverRegistry
{
    /** @var array<string,ClinicSpecialtyDriver> */
    protected static array $drivers = [];

    public static function register(ClinicSpecialtyDriver $driver): void
    {
        static::$drivers[$driver->key()] = $driver;
    }

    public static function get(?string $key): ?ClinicSpecialtyDriver
    {
        if ($key === null) return null;
        return static::$drivers[$key] ?? null;
    }

    public static function has(?string $key): bool
    {
        return $key !== null && isset(static::$drivers[$key]);
    }

    /**
     * @return array<string,ClinicSpecialtyDriver>
     */
    public static function all(): array
    {
        return static::$drivers;
    }

    /**
     * Registered specialty keys (those backed by a code plugin).
     *
     * @return array<int,string>
     */
    public static function keys(): array
    {
        return array_keys(static::$drivers);
    }

    /**
     * Specialty key => human label, for dropdowns.
     *
     * @return array<string,string>
     */
    public static function options(): array
    {
        return array_map(fn(ClinicSpecialtyDriver $d) => $d->label(), static::$drivers);
    }

    public static function flush(): void
    {
        static::$drivers = [];
    }
}
