<?php

namespace Modules\VetStaffPortal\Console;

use Illuminate\Console\Command;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Modules\VetStaffPortal\Services\StaffPushSender;

/**
 * Push recent ward/clinic updates to subscribed staff devices.
 *
 *   php artisan staff-portal:push-updates
 *
 * Scheduled every 15 min (live env). One sweep, three categories — each
 * cache-deduped so a re-run never double-sends:
 *   - alerts      → open va_alerts, broadcast to the business
 *   - admissions  → newly-admitted patients, to the attending doctor's device
 *   - schedule    → newly-booked future appointments, to the doctor's device
 */
class PushStaffUpdatesCommand extends Command
{
    protected $signature   = 'staff-portal:push-updates {--lookback=30 : minutes back to scan}';
    protected $description = 'Push new ward alerts, admissions, and bookings to subscribed staff devices';

    public function handle(StaffPushSender $sender): int
    {
        $since = Carbon::now()->subMinutes((int) $this->option('lookback'));
        $base  = rtrim(env('STAFF_PWA_URL', url('/staff-app/')), '/');
        $sent  = 0;

        $sent += $this->pushAlerts($sender, $since, $base);
        $sent += $this->pushAdmissions($sender, $since, $base);
        $sent += $this->pushSchedule($sender, $since, $base);

        $this->info("Dispatched {$sent} staff notification(s).");
        return self::SUCCESS;
    }

    /** Open ward alerts → broadcast to the business ('alerts'). */
    private function pushAlerts(StaffPushSender $sender, Carbon $since, string $base): int
    {
        if (! class_exists(\Modules\VetAdmission\Entities\VaAlert::class)) return 0;

        $alerts = \Modules\VetAdmission\Entities\VaAlert::with('admission.pet')
            ->whereNull('acknowledged_at')->where('raised_at', '>=', $since)
            ->orderBy('raised_at')->get();

        $count = 0;
        foreach ($alerts as $alert) {
            $key = "staff_push.alert.{$alert->id}";
            if (Cache::has($key)) continue;
            $pet = optional($alert->admission)->pet;
            $count += $sender->broadcastToBusiness((int) $alert->business_id, 'alerts', [
                'title'      => ($alert->severity === 'critical' ? '🔴 ' : '⚠️ ') . ($pet ? $pet->petname : 'Ward alert'),
                'body'       => $alert->message,
                'url'        => $base . ($alert->admission_id ? '/admissions/' . $alert->admission_id : '/alerts'),
                'icon'       => $base . '/icon-192.png',
                'tag'        => 'va-alert-' . $alert->id,
                'persistent' => $alert->severity === 'critical',
            ]);
            Cache::put($key, true, now()->addDay());
        }
        return $count;
    }

    /** Newly-admitted patients → the attending doctor's device ('admissions'). */
    private function pushAdmissions(StaffPushSender $sender, Carbon $since, string $base): int
    {
        if (! class_exists(\Modules\VetAdmission\Entities\VaAdmission::class)) return 0;

        $rows = \Modules\VetAdmission\Entities\VaAdmission::with('pet')
            ->where('status', 'admitted')->where('created_at', '>=', $since)
            ->whereNotNull('attending_doctor_id')->get();

        $count = 0;
        foreach ($rows as $a) {
            $key = "staff_push.admission.{$a->id}";
            if (Cache::has($key)) continue;
            $userId = $this->doctorUserId($a->attending_doctor_id);
            if ($userId) {
                $count += $sender->sendToUser($userId, 'admissions', [
                    'title' => '🏥 New admission assigned',
                    'body'  => (optional($a->pet)->petname ?? 'A patient') . ' was admitted to your care.',
                    'url'   => $base . '/admissions/' . $a->id,
                    'icon'  => $base . '/icon-192.png',
                    'tag'   => 'va-admission-' . $a->id,
                ]);
            }
            Cache::put($key, true, now()->addDay());
        }
        return $count;
    }

    /** Newly-booked future appointments → the doctor's device ('schedule'). */
    private function pushSchedule(StaffPushSender $sender, Carbon $since, string $base): int
    {
        if (! class_exists(\Modules\VetClinic\Entities\VcAppointment::class)) return 0;

        $rows = \Modules\VetClinic\Entities\VcAppointment::with('pet')
            ->where('created_at', '>=', $since)
            ->whereDate('appointment_date', '>=', Carbon::today())
            ->whereNotNull('doctor_id')
            ->whereNotIn('status', ['cancelled', 'no_show'])->get();

        $count = 0;
        foreach ($rows as $appt) {
            $key = "staff_push.appt.{$appt->id}";
            if (Cache::has($key)) continue;
            $userId = $this->doctorUserId($appt->doctor_id);
            if ($userId) {
                $when = Carbon::parse($appt->appointment_date)->format('d M')
                      . ' · ' . Carbon::parse($appt->appointment_time)->format('H:i');
                $count += $sender->sendToUser($userId, 'schedule', [
                    'title' => '📅 New appointment booked',
                    'body'  => (optional($appt->pet)->petname ?? 'A patient') . ' — ' . $when,
                    'url'   => $base . '/schedule',
                    'icon'  => $base . '/icon-192.png',
                    'tag'   => 'vc-appt-' . $appt->id,
                ]);
            }
            Cache::put($key, true, now()->addDay());
        }
        return $count;
    }

    /** Map a VcDoctor id → its linked ERP user id (cached briefly). */
    private function doctorUserId(?int $doctorId): ?int
    {
        if (! $doctorId) return null;
        return Cache::remember("staff_push.doctor_user.{$doctorId}", 300, function () use ($doctorId) {
            $d = \Modules\VetClinic\Entities\VcDoctor::find($doctorId);
            return $d?->user_id ? (int) $d->user_id : null;
        });
    }
}
