<?php

namespace Modules\ClinicCore\Entities;

use Illuminate\Database\Eloquent\Model;
use App\Contact;

class ClcAppointment extends Model
{
    protected $table = 'clc_appointments';
    protected $guarded = ['id'];

    protected $casts = [
        'appointment_date'        => 'date',
        'next_visit_date'         => 'date',
        'type_ids'                => 'array',
        'reason_ids'              => 'array',
        'next_visit_type_ids'     => 'array',
        'next_visit_reason_ids'   => 'array',
        'exam_results'            => 'array',
        'extra_vitals'            => 'array',
        'has_overlap'             => 'boolean',
        'arrived_at'              => 'datetime',
        'consultation_started_at' => 'datetime',
        'consultation_ended_at'   => 'datetime',
        // SIFA P3-T2 encounter extras + P3-T3 sign/lock
        'check_in_time'           => 'datetime',
        'discharge_time'          => 'datetime',
        'soap_signed_at'          => 'datetime',
        'soap_cosigned_at'        => 'datetime',
        'soap_locked'             => 'boolean',
    ];

    /** SIFA P3-T2 encounter enums (spec §7 encounter). */
    public const ENCOUNTER_TYPES = ['outpatient', 'inpatient', 'emergency', 'telemedicine', 'home_visit', 'day_care'];
    public const PRIORITIES      = ['routine', 'urgent', 'emergency'];

    public function statusLogs()
    {
        return $this->hasMany(ClcAppointmentStatusLog::class, 'appointment_id')->orderBy('changed_at');
    }

    public function editRequests()
    {
        return $this->hasMany(ClcAppointmentEditRequest::class, 'appointment_id')->latest();
    }

    public function doctorChangeRequests()
    {
        return $this->hasMany(ClcDoctorChangeRequest::class, 'appointment_id')->latest();
    }

    public function medicalReports()
    {
        return $this->hasMany(ClcMedicalReport::class, 'appointment_id');
    }

    public function nextAppointment()
    {
        return $this->belongsTo(ClcAppointment::class, 'next_appointment_id');
    }

    public function nextVisitDoctor()
    {
        return $this->belongsTo(ClcDoctor::class, 'next_visit_doctor_id');
    }

    public function nextVisitDepartment()
    {
        return $this->belongsTo(ClcDepartment::class, 'next_visit_department_id');
    }

    public function owner()
    {
        return $this->belongsTo(Contact::class, 'contact_id');
    }

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

    /** Alias for pet(): the patient this appointment belongs to. */
    public function patient()
    {
        return $this->belongsTo(ClcPatient::class, 'patient_id');
    }

    /** The clinical specialty this appointment is booked under. */
    public function specialty()
    {
        return $this->belongsTo(ClcSpecialty::class, 'specialty_id');
    }

    public function location()
    {
        return $this->belongsTo(ClcClinicLocation::class, 'location_id');
    }

    public function doctor()
    {
        return $this->belongsTo(ClcDoctor::class, 'doctor_id');
    }

    public function department()
    {
        return $this->belongsTo(ClcDepartment::class, 'department_id');
    }

    public function schedule()
    {
        return $this->belongsTo(ClcDoctorSchedule::class, 'schedule_id');
    }

    public function appointmentNotes()
    {
        return $this->hasMany(ClcAppointmentNote::class, 'appointment_id')->orderByDesc('created_at');
    }

    public function vaccinations()
    {
        return $this->hasMany(ClcVaccination::class, 'appointment_id');
    }

    public function prescriptions()
    {
        return $this->hasMany(ClcPrescription::class, 'appointment_id');
    }

    public function documents()
    {
        return $this->hasMany(ClcAppointmentDocument::class, 'appointment_id')->orderByDesc('created_at');
    }

    // ── SIFA P3-T2 / P3-T3 / P3-T4 relations ────────────────────────────

    /** Structured encounter diagnoses (P3-T2). */
    public function diagnoses()
    {
        return $this->hasMany(ClcAppointmentDiagnosis::class, 'appointment_id')->orderBy('id');
    }

    /** SOAP note amendment history (P3-T3). */
    public function noteAmendments()
    {
        return $this->hasMany(ClcNoteAmendment::class, 'appointment_id')->orderByDesc('created_at');
    }

    /** Trend-capable vitals readings for this encounter (P3-T4). */
    public function vitals()
    {
        return $this->hasMany(ClcVital::class, 'appointment_id')->orderByDesc('recorded_at');
    }

    /** Parent encounter for follow-ups / transfers (P3-T2). */
    public function parentAppointment()
    {
        return $this->belongsTo(ClcAppointment::class, 'parent_appointment_id');
    }

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

    /** True when the SOAP note is signed & locked (P3-T3). */
    public function isSoapLocked(): bool
    {
        return (bool) ($this->soap_locked ?? false);
    }

    public function getStatusColorAttribute()
    {
        return [
            'pending'     => 'warning',
            'waiting'     => 'warning',
            'confirmed'   => 'info',
            'in_progress' => 'primary',
            'completed'   => 'success',
            'cancelled'   => 'danger',
            'no_show'     => 'default',
        ][$this->status] ?? 'default';
    }

    public function scopeForBusiness($query, $businessId)
    {
        return $query->where('business_id', $businessId);
    }
}
