<?php

namespace App\Services\Care\Emergency;

use App\Models\Appointment;
use App\Models\Consultation;
use App\Models\Organization;
use App\Models\Visit;
use App\Models\VitalSign;
use App\Services\Care\ConsultationService;
use Illuminate\Support\Collection;

class EmergencyVitalsService
{
    public function __construct(
        protected ConsultationService $consultations,
    ) {}

    /**
     * @return Collection<int, VitalSign>
     */
    public function forVisit(Visit $visit): Collection
    {
        $consultationIds = Consultation::owned($visit->owner_ref)
            ->where('visit_id', $visit->id)
            ->pluck('id');

        if ($consultationIds->isEmpty()) {
            return collect();
        }

        return VitalSign::owned($visit->owner_ref)
            ->whereIn('consultation_id', $consultationIds)
            ->orderByDesc('recorded_at')
            ->orderByDesc('id')
            ->get();
    }

    public function latestForVisit(Visit $visit): ?VitalSign
    {
        return $this->forVisit($visit)->first();
    }

    /**
     * @param  array<string, mixed>  $vitals
     */
    public function record(
        Organization $organization,
        Visit $visit,
        string $ownerRef,
        array $vitals,
        ?string $actorRef = null,
    ): VitalSign {
        $consultation = $this->ensureConsultation($visit, $ownerRef, $actorRef);

        $saved = $this->consultations->saveVitals(
            $consultation,
            $ownerRef,
            $vitals,
            $actorRef,
        );

        if (! $saved) {
            throw new \InvalidArgumentException('Enter at least one vital sign value.');
        }

        return $saved;
    }

    protected function ensureConsultation(Visit $visit, string $ownerRef, ?string $actorRef): Consultation
    {
        $existing = Consultation::owned($ownerRef)
            ->where('visit_id', $visit->id)
            ->where('status', '!=', Consultation::STATUS_COMPLETED)
            ->orderByDesc('id')
            ->first();

        if ($existing) {
            return $existing;
        }

        $completed = Consultation::owned($ownerRef)
            ->where('visit_id', $visit->id)
            ->orderByDesc('id')
            ->first();

        if ($completed) {
            return $completed;
        }

        $visit->loadMissing('appointment', 'patient');
        $appointment = $visit->appointment;
        if (! $appointment instanceof Appointment) {
            $appointment = Appointment::query()->where('visit_id', $visit->id)->first();
        }

        if ($appointment) {
            try {
                return $this->consultations->startFromAppointment($appointment, $ownerRef, $actorRef);
            } catch (\InvalidArgumentException) {
                // Fall through to draft consultation.
            }
        }

        return Consultation::create([
            'owner_ref' => $ownerRef,
            'visit_id' => $visit->id,
            'appointment_id' => $appointment?->id,
            'practitioner_id' => $appointment?->practitioner_id,
            'patient_id' => $visit->patient_id,
            'status' => Consultation::STATUS_DRAFT,
            'started_at' => now(),
        ]);
    }
}
