<?php

namespace Modules\ClinicCore\Entities;

use Illuminate\Database\Eloquent\Model;
use Modules\ClinicCore\Entities\Services\SpecialtyDriverRegistry;

/**
 * A clinical specialty (Dermatology, Dental, Cardiology, Internal Medicine, …).
 *
 * Most specialties are pure configuration rows seeded globally
 * (business_id null) and shared by every business. A specialty MAY be backed
 * by a code plugin that registers a driver with the SpecialtyDriverRegistry;
 * such rows have is_structural = true and a driver_key.
 */
class ClcSpecialty extends Model
{
    protected $table = 'clc_specialties';
    protected $guarded = ['id'];

    protected $casts = [
        'config'        => 'array',
        'capabilities'  => 'array',
        'is_structural' => 'boolean',
        'is_active'     => 'boolean',
    ];

    /**
     * Read a capability flag for this specialty. Falls back to the `config`
     * JSON (capabilities key) and finally the supplied default. Per-business
     * overrides and driver overrides are resolved in ClinicCapabilities.
     */
    public function capability(string $key, $default = null)
    {
        $caps = $this->capabilities ?? [];
        if (is_array($caps) && array_key_exists($key, $caps)) {
            return (bool) $caps[$key];
        }
        $cfgCaps = (array) data_get($this->config, 'capabilities', []);
        if (array_key_exists($key, $cfgCaps)) {
            return (bool) $cfgCaps[$key];
        }
        return $default;
    }

    /**
     * Extra vital-sign fields specific to this specialty. Merges a structural
     * driver's optional vitalFields() with the config['vital_fields'] rows.
     * Each entry: ['key','label','unit','type'(number|text)].
     *
     * @return array<int,array<string,mixed>>
     */
    public function extraVitalFields(): array
    {
        $fields = [];
        try {
            if ($this->hasDriver() && ($driver = $this->driver()) && method_exists($driver, 'vitalFields')) {
                $dv = $driver->vitalFields();
                if (is_array($dv)) $fields = array_merge($fields, $dv);
            }
        } catch (\Throwable $e) { /* ignore driver issues */ }

        $cfg = (array) data_get($this->config, 'vital_fields', []);
        if ($cfg) $fields = array_merge($fields, $cfg);

        // De-dup by key, keep first occurrence.
        $seen = [];
        return array_values(array_filter($fields, function ($f) use (&$seen) {
            $k = $f['key'] ?? null;
            if (!$k || isset($seen[$k])) return false;
            $seen[$k] = true;
            return true;
        }));
    }

    public function appointments()
    {
        return $this->hasMany(ClcAppointment::class, 'specialty_id');
    }

    /** Specialties visible to a business: its own rows plus the global catalog. */
    public function scopeForBusiness($query, $businessId)
    {
        return $query->where(function ($q) use ($businessId) {
            $q->whereNull('business_id')->orWhere('business_id', $businessId);
        });
    }

    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    /** The registered code driver for this specialty, or null (config-only). */
    public function driver()
    {
        return SpecialtyDriverRegistry::get($this->driver_key ?: $this->code);
    }

    public function hasDriver(): bool
    {
        return SpecialtyDriverRegistry::has($this->driver_key ?: $this->code);
    }
}
