<?php

declare(strict_types=1);

namespace ImovelZapAi\Visits\Application\Services;

use ImovelZapAi\Visits\Domain\Enums\VisitReminderStatus;
use ImovelZapAi\Visits\Domain\Enums\VisitReminderType;
use ImovelZapAi\Visits\Infrastructure\Jobs\SendVisitReminderJob;
use ImovelZapAi\Visits\Infrastructure\Persistence\Eloquent\VisitModel;
use ImovelZapAi\Visits\Infrastructure\Persistence\Eloquent\VisitReminderModel;

final class VisitReminderScheduler
{
    public function __construct(
        private readonly VisitMessageRenderer $renderer,
    ) {}

    public function scheduleForVisit(VisitModel $visit, bool $sendInitialNow = true): void
    {
        if ($visit->scheduled_start === null) {
            return;
        }

        $this->renderer->ensureDefaultTemplates($visit->tenant_id);
        $this->cancelPending($visit->id);

        $start = $visit->scheduled_start;

        $plan = [
            VisitReminderType::InitialConfirmation->value => $sendInitialNow ? now() : $start->copy()->subMinutes(5),
            VisitReminderType::Reminder24h->value => $start->copy()->subHours((int) config('visits.reminders.hours_before_24h', 24)),
            VisitReminderType::Reminder2h->value => $start->copy()->subHours((int) config('visits.reminders.hours_before_2h', 2)),
            VisitReminderType::PresenceConfirmation->value => $start->copy()->subMinutes(30),
        ];

        foreach ($plan as $typeValue => $when) {
            $type = VisitReminderType::from($typeValue);

            if ($this->renderer->templateBody($visit->tenant_id, $type) === null) {
                continue;
            }

            if ($when->lessThanOrEqualTo(now()->subMinute()) && $type !== VisitReminderType::InitialConfirmation) {
                continue;
            }

            $reminder = VisitReminderModel::query()->updateOrCreate(
                [
                    'visit_id' => $visit->id,
                    'type' => $type,
                ],
                [
                    'tenant_id' => $visit->tenant_id,
                    'status' => VisitReminderStatus::Pending,
                    'scheduled_for' => $when->greaterThan(now()) ? $when : now(),
                    'sent_at' => null,
                    'message_body' => null,
                    'error_message' => null,
                ],
            );

            if ($reminder->scheduled_for->lessThanOrEqualTo(now()->addMinute())) {
                SendVisitReminderJob::dispatch($reminder->id, $visit->tenant_id)
                    ->onQueue((string) config('visits.queue', 'visits'));
            }
        }
    }

    public function cancelPending(string $visitId): void
    {
        VisitReminderModel::query()
            ->where('visit_id', $visitId)
            ->where('status', VisitReminderStatus::Pending)
            ->update(['status' => VisitReminderStatus::Cancelled]);
    }
}
