<?php

namespace Modules\OphthalmologyClinic\Entities;

use Illuminate\Database\Eloquent\Model;
use Modules\ClinicCore\Entities\ClcPatient;

/**
 * A per-visit ophthalmology exam (OD/OS) on a shared ClinicCore patient
 * (1:many, trend-capable). The 1:1 OphthPatientProfile stays the at-a-glance
 * summary; this is the full historical record behind the IOP / VA trends and
 * the glaucoma & diabetic-retinopathy tracking.
 */
class OpthEyeExam extends Model
{
    protected $table = 'opth_eye_exams';
    protected $guarded = ['id'];

    protected $casts = [
        'slit_lamp'   => 'array',
        'fundus'      => 'array',
        'examined_at' => 'datetime',
        'sphere_od'   => 'float', 'sphere_os'   => 'float',
        'cylinder_od' => 'float', 'cylinder_os' => 'float',
        'add_od'      => 'float', 'add_os'      => 'float',
        'iop_od'      => 'float', 'iop_os'      => 'float',
        'cup_disc_od' => 'float', 'cup_disc_os' => 'float',
    ];

    public const IOP_METHODS = [
        'goldmann' => 'Goldmann',
        'air_puff' => 'Air puff',
        'icare'    => 'iCare',
        'tonopen'  => 'Tono-pen',
    ];

    public const DR_GRADES = [
        'R0' => 'R0 — none',
        'R1' => 'R1 — background',
        'R2' => 'R2 — pre-proliferative',
        'R3' => 'R3 — proliferative',
    ];

    public const MACULOPATHY = [
        'M0' => 'M0 — none',
        'M1' => 'M1 — maculopathy',
    ];

    /** IOP above this in EITHER eye raises a critical_value medical alert. */
    public const IOP_CRITICAL = 30.0;

    public function patient()
    {
        return $this->belongsTo(ClcPatient::class, 'patient_id');
    }

    /** True when either eye's IOP breaches the critical threshold. */
    public function iopCritical(): bool
    {
        return ($this->iop_od !== null && $this->iop_od > self::IOP_CRITICAL)
            || ($this->iop_os !== null && $this->iop_os > self::IOP_CRITICAL);
    }

    /** Worst DR grade across both eyes (numeric R-level), for the referral hint. */
    public function worstDrLevel(): int
    {
        $lvl = 0;
        foreach ([$this->dr_grade_od, $this->dr_grade_os] as $g) {
            if ($g && preg_match('/^R(\d)$/', $g, $m)) {
                $lvl = max($lvl, (int) $m[1]);
            }
        }
        return $lvl;
    }
}
