<?php

namespace Modules\PortalApi\Console;

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

/**
 * Scans vc_vaccinations and pushes a reminder to the pet's owner at:
 *   T-30d   (vaccine_due_30 marker)
 *   T-7d    (vaccine_due_7)
 *   T-0     (vaccine_due_today)
 *   T+1d    (vaccine_overdue)
 *
 * Idempotent — uses tag "vax-<id>-<bucket>" so the SW collapses repeats
 * AND we mark sent ones in a tiny portal_push_sent_log table to skip
 * across runs.
 *
 *   php artisan portal:push:vaccinations  [--dry]
 *
 * Wire in app/Console/Kernel.php:
 *   $schedule->command('portal:push:vaccinations')->dailyAt('08:00');
 */
class PushVaxRemindersCommand extends Command
{
    protected $signature   = 'portal:push:vaccinations {--dry : log what would be sent without delivering}';
    protected $description = 'Push vaccination reminders (T-30, T-7, T-0, T+1) to pet owners via the PWA.';

    public function handle(PortalPushSender $sender): int
    {
        $this->ensureLogTable();

        $today = Carbon::today();
        $buckets = [
            ['days' =>  30, 'tag' => 'vax_due_30',    'body' => 'is due in 30 days'],
            ['days' =>   7, 'tag' => 'vax_due_7',     'body' => 'is due in 7 days'],
            ['days' =>   0, 'tag' => 'vax_due_today', 'body' => 'is due today'],
            ['days' =>  -1, 'tag' => 'vax_overdue',   'body' => 'is overdue'],
        ];

        $totalSent = 0;
        foreach ($buckets as $b) {
            $targetDate = $today->copy()->addDays($b['days']);
            $rows = DB::table('vc_vaccinations as v')
                ->join('vc_pets as p', 'p.id', '=', 'v.pet_id')
                ->leftJoin('vc_vaccine_types as t', 't.id', '=', 'v.vaccine_type_id')
                ->leftJoin('portal_owners as po', function ($j) {
                    $j->on('po.business_id', '=', 'v.business_id')
                      ->on('po.contact_id', '=', 'v.contact_id');
                })
                ->whereDate('v.next_due_date', $targetDate->toDateString())
                ->whereNull('v.waived_at')
                ->where('po.is_active', true)
                ->whereNotNull('po.id')
                ->select(
                    'v.id as vax_id',
                    'p.id as pet_id', 'p.petname',
                    't.name as vaccine_name',
                    'po.id as owner_id', 'po.name as owner_name'
                )
                ->get();

            foreach ($rows as $row) {
                if ($this->wasSent((int) $row->vax_id, $b['tag'])) continue;

                $payload = [
                    'title' => "{$row->petname}'s " . ($row->vaccine_name ?: 'vaccine') . " " . $b['body'],
                    'body'  => "Tap to book the next visit.",
                    'url'   => '/app/book?pet_id=' . $row->pet_id,
                    'tag'   => 'vax-' . $row->vax_id . '-' . $b['tag'],
                ];

                $this->line(sprintf('  → owner_id=%d  vax_id=%d  %s', $row->owner_id, $row->vax_id, $b['tag']));

                if (! $this->option('dry')) {
                    $sent = $sender->sendToOwner((int) $row->owner_id, 'vaccinations', $payload);
                    if ($sent > 0) {
                        $this->markSent((int) $row->vax_id, $b['tag']);
                        $totalSent += $sent;
                    }
                }
            }
        }

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

    /* ─── Tiny sent-log so we never double-push the same bucket ─── */

    private function ensureLogTable(): void
    {
        if (DB::getSchemaBuilder()->hasTable('portal_push_sent_log')) return;
        DB::getSchemaBuilder()->create('portal_push_sent_log', function ($t) {
            $t->bigIncrements('id');
            $t->string('kind', 32);          // 'vax', 'apt'
            $t->unsignedBigInteger('subject_id');
            $t->string('bucket', 32);
            $t->timestamp('sent_at')->useCurrent();
            $t->unique(['kind', 'subject_id', 'bucket']);
        });
    }

    private function wasSent(int $subjectId, string $bucket): bool
    {
        return DB::table('portal_push_sent_log')
            ->where('kind', 'vax')
            ->where('subject_id', $subjectId)
            ->where('bucket', $bucket)
            ->exists();
    }

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