<?php

namespace Modules\GynaecologyClinic\Entities;

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

/**
 * Obstetrics & Gynaecology 1:1 extension of a shared ClinicCore patient, with
 * derived obstetric values (GPAL summary, gestational age, EDD by Naegele's
 * rule). This is the plugin half of the ClinicCore specialty architecture.
 */
class ObgynPatientProfile extends Model
{
    protected $table = 'obgyn_patient_profiles';
    protected $guarded = ['id'];

    protected $casts = [
        'lmp_date'      => 'date',
        'cycle_regular' => 'boolean',
        'is_pregnant'   => 'boolean',
        'menopause'     => 'boolean',
    ];

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

    /** Obstetric score, e.g. "G3 P2 A1 L2". Null if nothing recorded. */
    public function gpal(): ?string
    {
        if ($this->gravida === null && $this->para === null
            && $this->abortions === null && $this->living === null) {
            return null;
        }
        return sprintf('G%d P%d A%d L%d',
            (int) $this->gravida, (int) $this->para, (int) $this->abortions, (int) $this->living);
    }

    /** Estimated due date (Naegele's rule: LMP + 280 days). */
    public function edd(): ?Carbon
    {
        return $this->lmp_date ? $this->lmp_date->copy()->addDays(280) : null;
    }

    /** Gestational age in completed days from LMP (only while pregnant). */
    public function gestationalDays(): ?int
    {
        if (! $this->is_pregnant || ! $this->lmp_date) return null;
        $days = $this->lmp_date->diffInDays(Carbon::today(), false);
        return ($days >= 0 && $days <= 310) ? $days : null;
    }

    /** Gestational age formatted as "32w 4d". */
    public function gestationalAge(): ?string
    {
        $days = $this->gestationalDays();
        if ($days === null) return null;
        return intdiv($days, 7) . 'w ' . ($days % 7) . 'd';
    }
}
