<?php

namespace Modules\VetClinic\Entities;

use Illuminate\Database\Eloquent\Model;

/**
 * Item 1.4 - one question/observation inside a VcExamTemplate.
 *
 * response_type drives the UI widget; options_json carries the per-option
 * severity + critical flags for select/grade types. For measurements the
 * critical_low/high columns are the hard out-of-range bounds the
 * Medical Critical Check report (4.1) flags on.
 */
class VcExamTemplateItem extends Model
{
    protected $table = 'vc_exam_template_items';
    protected $guarded = ['id'];

    protected $casts = [
        'options_json'   => 'array',
        'normal_low'     => 'decimal:3',
        'normal_high'    => 'decimal:3',
        'critical_low'   => 'decimal:3',
        'critical_high'  => 'decimal:3',
        'is_required'    => 'boolean',
        'sort_order'     => 'integer',
    ];

    public function template()
    {
        return $this->belongsTo(VcExamTemplate::class, 'template_id');
    }

    public function findings()
    {
        return $this->hasMany(VcAppointmentExamFinding::class, 'template_item_id');
    }

    /**
     * Compute severity (0-3) and is_critical for a given submitted value,
     * based on this item's response_type and configured bounds.
     *
     *   - select / multi_select / grade -> look up the option's severity
     *   - measurement -> critical bounds first, then normal bounds
     *   - text / yes_no -> always 0 unless explicitly flagged
     *
     * Returns ['severity' => 0..3, 'is_critical' => bool, 'numeric' => float|null].
     */
    public function scoreValue($value): array
    {
        $sev = 0; $crit = false; $num = null;
        $type = $this->response_type;

        if (in_array($type, ['select', 'multi_select', 'grade'], true)) {
            $needles = is_array($value) ? $value : [$value];
            foreach ($needles as $needle) {
                foreach ($this->options_json ?? [] as $opt) {
                    if (((string) ($opt['value'] ?? $opt['label'] ?? '')) === (string) $needle) {
                        $sev  = max($sev, (int) ($opt['severity']   ?? 0));
                        $crit = $crit || (bool) ($opt['is_critical'] ?? false);
                        break;
                    }
                }
            }
        } elseif ($type === 'measurement') {
            $num = is_numeric($value) ? (float) $value : null;
            if ($num !== null) {
                if (($this->critical_low  !== null && $num < $this->critical_low) ||
                    ($this->critical_high !== null && $num > $this->critical_high)) {
                    $sev = 3; $crit = true;
                } elseif (($this->normal_low  !== null && $num < $this->normal_low) ||
                          ($this->normal_high !== null && $num > $this->normal_high)) {
                    $sev = 2;
                }
            }
        }
        return ['severity' => $sev, 'is_critical' => $crit, 'numeric' => $num];
    }
}
