<?php

namespace App\Services\Care\Dentistry;

use App\Models\DentalRecall;
use App\Models\Organization;
use App\Models\Patient;
use App\Models\Visit;
use App\Services\Care\AuditLogger;
use Illuminate\Support\Collection;

class DentalRecallService
{
    /**
     * @return Collection<int, DentalRecall>
     */
    public function recallsForPatient(Organization $organization, Patient $patient, string $ownerRef, int $limit = 30): Collection
    {
        return DentalRecall::owned($ownerRef)
            ->where('organization_id', $organization->id)
            ->where('patient_id', $patient->id)
            ->orderBy('due_on')
            ->limit($limit)
            ->get();
    }

    /**
     * @param  array{due_on: string, reason?: ?string, notes?: ?string}  $data
     */
    public function schedule(
        Organization $organization,
        Patient $patient,
        string $ownerRef,
        array $data,
        ?string $actorRef = null,
    ): DentalRecall {
        $dueOn = (string) ($data['due_on'] ?? '');
        if ($dueOn === '') {
            throw new \InvalidArgumentException('Recall due date is required.');
        }

        $status = DentalRecall::STATUS_SCHEDULED;
        if (now()->startOfDay()->gte(\Carbon\Carbon::parse($dueOn)->startOfDay())) {
            $status = DentalRecall::STATUS_DUE;
        }

        $recall = DentalRecall::create([
            'owner_ref' => $ownerRef,
            'organization_id' => $organization->id,
            'patient_id' => $patient->id,
            'due_on' => $dueOn,
            'reason' => $data['reason'] ?? null,
            'status' => $status,
            'notes' => $data['notes'] ?? null,
            'created_by' => $actorRef ?? $ownerRef,
        ]);

        AuditLogger::record($ownerRef, 'dental.recall.scheduled', $organization->id, $actorRef, DentalRecall::class, $recall->id);

        return $recall;
    }

    public function complete(
        DentalRecall $recall,
        string $ownerRef,
        ?Visit $visit = null,
        ?string $actorRef = null,
    ): DentalRecall {
        $recall->update([
            'status' => DentalRecall::STATUS_COMPLETED,
            'linked_visit_id' => $visit?->id ?? $recall->linked_visit_id,
        ]);

        AuditLogger::record($ownerRef, 'dental.recall.completed', $recall->organization_id, $actorRef, DentalRecall::class, $recall->id);

        return $recall->fresh();
    }

    public function cancel(DentalRecall $recall, string $ownerRef, ?string $actorRef = null): DentalRecall
    {
        $recall->update(['status' => DentalRecall::STATUS_CANCELLED]);

        AuditLogger::record($ownerRef, 'dental.recall.cancelled', $recall->organization_id, $actorRef, DentalRecall::class, $recall->id);

        return $recall->fresh();
    }

    /**
     * @return Collection<int, DentalRecall>
     */
    public function openForPatient(Organization $organization, Patient $patient, string $ownerRef): Collection
    {
        return DentalRecall::owned($ownerRef)
            ->where('organization_id', $organization->id)
            ->where('patient_id', $patient->id)
            ->whereIn('status', [DentalRecall::STATUS_SCHEDULED, DentalRecall::STATUS_DUE])
            ->orderBy('due_on')
            ->get();
    }
}
