<?php

declare(strict_types=1);

namespace ImovelZapAi\Visits\Application\Actions;

use ImovelZapAi\Conversations\Infrastructure\Persistence\Eloquent\ContactModel;
use ImovelZapAi\Conversations\Infrastructure\Persistence\Eloquent\ConversationModel;
use ImovelZapAi\Visits\Application\Ports\VisitOutboundMessengerInterface;
use ImovelZapAi\Visits\Application\Services\VisitLogWriter;
use ImovelZapAi\Visits\Application\Services\VisitMessageRenderer;
use ImovelZapAi\Visits\Domain\Enums\VisitLogEvent;
use ImovelZapAi\Visits\Domain\Enums\VisitReminderStatus;
use ImovelZapAi\Visits\Infrastructure\Persistence\Eloquent\VisitReminderModel;
use ImovelZapAi\Tenancy\Support\TenantContext;

final class SendVisitReminderAction
{
    public function __construct(
        private readonly VisitMessageRenderer $renderer,
        private readonly VisitOutboundMessengerInterface $outbound,
        private readonly VisitLogWriter $logWriter,
    ) {}

    public function execute(string $reminderId, string $tenantId): VisitReminderModel
    {
        TenantContext::set($tenantId);

        try {
            $reminder = VisitReminderModel::query()
                ->where('tenant_id', $tenantId)
                ->whereKey($reminderId)
                ->with(['visit.contact', 'visit.property', 'visit.conversation'])
                ->firstOrFail();

            if ($reminder->status !== VisitReminderStatus::Pending) {
                return $reminder;
            }

            $visit = $reminder->visit;
            if ($visit === null || $visit->status->isTerminal()) {
                $reminder->forceFill([
                    'status' => VisitReminderStatus::Cancelled,
                    'error_message' => 'Visita terminal — lembrete cancelado.',
                ])->save();

                return $reminder;
            }

            $body = $this->renderer->render($tenantId, $reminder->type, $visit);
            if ($body === null) {
                $reminder->forceFill([
                    'status' => VisitReminderStatus::Cancelled,
                    'error_message' => 'Template desabilitado.',
                ])->save();

                return $reminder;
            }

            try {
                /** @var ContactModel $contact */
                $contact = $visit->contact;
                $conversation = $visit->conversation_id !== null
                    ? ConversationModel::query()->find($visit->conversation_id)
                    : null;

                $this->outbound->send($tenantId, $contact, $body, $conversation);

                $reminder->forceFill([
                    'status' => VisitReminderStatus::Sent,
                    'sent_at' => now(),
                    'message_body' => $body,
                    'error_message' => null,
                ])->save();

                $this->logWriter->write(
                    $tenantId,
                    $visit->id,
                    VisitLogEvent::ReminderSent,
                    message: $reminder->type->label().' enviado.',
                );
            } catch (\Throwable $e) {
                $reminder->forceFill([
                    'status' => VisitReminderStatus::Failed,
                    'error_message' => $e->getMessage(),
                    'message_body' => $body,
                ])->save();

                $this->logWriter->write(
                    $tenantId,
                    $visit->id,
                    VisitLogEvent::ReminderFailed,
                    message: $e->getMessage(),
                );
            }

            return $reminder->fresh();
        } finally {
            TenantContext::clear();
        }
    }
}
