<?php

namespace Modules\MedEmergency\Entities;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;

/**
 * An emergency-department visit (SIFA P6-T3). Board transitions, triage stamping
 * and disposition are orchestrated by the controllers / TriageService; this
 * model owns the reference-number allocator and the board/triage constants.
 */
class MderVisit extends Model
{
    protected $table = 'mder_visits';

    protected $guarded = ['id'];

    protected $casts = [
        'arrival_at'     => 'datetime',
        'triaged_at'     => 'datetime',
        'disposition_at' => 'datetime',
    ];

    public const ARRIVAL_MODES = ['walk_in', 'ambulance', 'police', 'transfer', 'other'];

    public const TRIAGE_LEVELS = ['resuscitation', 'emergent', 'urgent', 'less_urgent', 'non_urgent'];

    public const TRIAGE_SYSTEMS = ['esi', 'manchester', 'ctas'];

    /** ER board columns, in left-to-right order. */
    public const BOARD_STATUSES = [
        'awaiting_triage', 'to_be_seen', 'in_progress', 'pending_results',
        'pending_disposition', 'admitted_awaiting_bed', 'done',
    ];

    public const DISPOSITIONS = ['discharged', 'admitted', 'transferred', 'expired', 'lwbs', 'ama'];

    /** Bootstrap-ish colour per triage level for the board cards. */
    public const TRIAGE_COLORS = [
        'resuscitation' => '#b91c1c', // red
        'emergent'      => '#ea580c', // orange
        'urgent'        => '#ca8a04', // amber
        'less_urgent'   => '#16a34a', // green
        'non_urgent'    => '#2563eb', // blue
    ];

    public function events()
    {
        return $this->hasMany(MderVisitEvent::class, 'visit_id')->orderBy('id');
    }

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

    /** True once the visit has left the board (disposition recorded / done). */
    public function isClosed(): bool
    {
        return $this->board_status === 'done'
            || in_array($this->disposition, ['discharged', 'transferred', 'expired', 'lwbs', 'ama'], true);
    }

    /** Minutes elapsed in the department (arrival → disposition, or → now). */
    public function timeInDeptMinutes(): ?int
    {
        if (! $this->arrival_at) {
            return null;
        }
        $end = $this->disposition_at ?: now();

        return $this->arrival_at->diffInMinutes($end);
    }

    /** Allocate the next visit reference: ER-{biz}-{0000001}. */
    public static function nextVisitNo(int $businessId): string
    {
        return DB::transaction(function () use ($businessId) {
            $last = static::where('business_id', $businessId)
                ->lockForUpdate()->orderByDesc('id')->value('visit_no');
            $n = 1;
            if ($last && preg_match('/-(\d+)$/', $last, $m)) {
                $n = ((int) $m[1]) + 1;
            }

            return 'ER-' . $businessId . '-' . str_pad((string) $n, 7, '0', STR_PAD_LEFT);
        });
    }
}
