<?php

namespace Modules\PortalApi\Console;

use Illuminate\Console\Command;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Modules\PortalApi\Services\Push\PortalPushSender;

/**
 * Pushes "you have an appointment tomorrow" to owners 24h before
 * scheduled appointments that haven't been cancelled.
 *
 *   php artisan portal:push:appointments  [--dry]
 *
 * Wire in app/Console/Kernel.php:
 *   $schedule->command('portal:push:appointments')->hourly();
 */
class PushAppointmentRemindersCommand extends Command
{
    protected $signature   = 'portal:push:appointments {--dry : log what would be sent without delivering}';
    protected $description = 'Push T-24h appointment reminders to pet owners via the PWA.';

    public function handle(PortalPushSender $sender): int
    {
        // Window: appointments starting between 23h and 25h from now (gives
        // us 2h slack so an hourly cron always catches them once).
        $from = now()->copy()->addHours(23);
        $to   = now()->copy()->addHours(25);

        $rows = DB::table('vc_appointments as a')
            ->join('vc_pets as p', 'p.id', '=', 'a.pet_id')
            ->leftJoin('vc_doctors as d', 'd.id', '=', 'a.doctor_id')
            ->leftJoin('portal_owners as po', function ($j) {
                $j->on('po.business_id', '=', 'a.business_id')
                  ->on('po.contact_id', '=', 'a.contact_id');
            })
            ->whereIn('a.status', ['pending', 'confirmed'])
            ->whereNotNull('po.id')
            ->where('po.is_active', true)
            ->whereRaw("CONCAT(a.appointment_date, ' ', COALESCE(a.appointment_time, '00:00:00')) BETWEEN ? AND ?",
                       [$from->format('Y-m-d H:i:s'), $to->format('Y-m-d H:i:s')])
            ->select(
                'a.id as apt_id', 'a.appointment_date', 'a.appointment_time',
                'a.type', 'p.petname',
                'd.name as doctor_name',
                'po.id as owner_id'
            )
            ->get();

        $sent = 0;
        foreach ($rows as $row) {
            if ($this->wasSent((int) $row->apt_id)) continue;

            $dt = Carbon::parse(
                $row->appointment_date . ' ' . ($row->appointment_time ?? '00:00:00')
            );
            $payload = [
                'title' => 'Reminder: ' . ($row->type ?: 'Visit') . ' tomorrow',
                'body'  => "{$row->petname} · " . $dt->format('D M j · H:i')
                         . ($row->doctor_name ? " with {$row->doctor_name}" : ''),
                'url'   => '/app/appointments',
                'tag'   => 'apt-' . $row->apt_id,
            ];

            $this->line("  → owner_id={$row->owner_id}  apt_id={$row->apt_id}");
            if (! $this->option('dry')) {
                $n = $sender->sendToOwner((int) $row->owner_id, 'appointments', $payload);
                if ($n > 0) { $this->markSent((int) $row->apt_id); $sent += $n; }
            }
        }

        $this->info(($this->option('dry') ? '[dry-run] ' : '') . "Done. {$sent} push(es) sent.");
        return self::SUCCESS;
    }

    private function wasSent(int $apt): bool
    {
        return DB::table('portal_push_sent_log')
            ->where('kind', 'apt')->where('subject_id', $apt)->where('bucket', 't-24h')
            ->exists();
    }

    private function markSent(int $apt): void
    {
        DB::table('portal_push_sent_log')->insertOrIgnore([
            'kind' => 'apt', 'subject_id' => $apt, 'bucket' => 't-24h', 'sent_at' => now(),
        ]);
    }
}
