<?php

declare(strict_types=1);

namespace ImovelZapAi\Conversations\Application\Actions;

use ImovelZapAi\Conversations\Application\Data\CatalogReplyButton;
use ImovelZapAi\Conversations\Application\Services\ConversationAutomationState;
use ImovelZapAi\Conversations\Application\Services\MessagingConfigResolver;
use ImovelZapAi\Conversations\Application\Services\PropertyCatalogFormatter;
use ImovelZapAi\Conversations\Domain\Enums\ConversationAutomationPhase;
use ImovelZapAi\Conversations\Domain\Enums\MessageDeliveryStatus;
use ImovelZapAi\Conversations\Domain\Enums\MessagingProvider;
use ImovelZapAi\Conversations\Infrastructure\Persistence\Eloquent\ContactModel;
use ImovelZapAi\Conversations\Infrastructure\Persistence\Eloquent\ConversationModel;
use ImovelZapAi\Conversations\Infrastructure\Persistence\Eloquent\MessageModel;
use ImovelZapAi\Properties\Application\Services\PropertyMediaUrlResolver;
use ImovelZapAi\Properties\Infrastructure\Persistence\Eloquent\PropertyModel;

final class PresentCatalogPropertyAction
{
    public function __construct(
        private readonly PropertyCatalogFormatter $formatter,
        private readonly PropertyMediaUrlResolver $mediaUrls,
        private readonly MessagingConfigResolver $configResolver,
        private readonly SendOutboundMessageAction $sendText,
        private readonly SendOutboundImageAction $sendImage,
        private readonly SendOutboundButtonsAction $sendButtons,
        private readonly ConversationAutomationState $automationState,
    ) {}

    public function execute(
        string $tenantId,
        ContactModel $contact,
        ConversationModel $conversation,
        int $index,
    ): void {
        /** @var list<string> $propertyIds */
        $propertyIds = $conversation->context['catalog']['property_ids'] ?? [];
        $total = count($propertyIds);

        if ($total === 0 || ! isset($propertyIds[$index])) {
            $this->sendText->execute(
                $tenantId,
                $contact,
                $this->formatter->catalogExhaustedMessage(),
                $conversation,
            );

            return;
        }

        $property = PropertyModel::query()
            ->where('tenant_id', $tenantId)
            ->whereKey($propertyIds[$index])
            ->with(['neighborhood', 'city', 'images'])
            ->first();

        if ($property === null) {
            $this->sendText->execute(
                $tenantId,
                $contact,
                $this->formatter->catalogExhaustedMessage(),
                $conversation,
            );

            return;
        }

        $caption = $this->formatter->card($index + 1, $total, $property);
        $media = $this->mediaUrls->forMessaging($property->coverImage());
        $propertyDelivered = false;

        if ($media !== null) {
            $imageMessage = $this->sendImage->execute(
                tenantId: $tenantId,
                contact: $contact,
                imageUrl: $media,
                caption: $caption,
                conversation: $conversation,
            );

            $propertyDelivered = $this->wasSent($imageMessage);
        }

        if (! $propertyDelivered) {
            $this->sendText->execute(
                tenantId: $tenantId,
                contact: $contact,
                body: $caption,
                conversation: $conversation,
            );
        }

        $hasNext = $total > 1 && ($index + 1) < $total;

        $this->sendText->execute(
            tenantId: $tenantId,
            contact: $contact,
            body: $this->formatter->actionMenu($hasNext),
            conversation: $conversation,
        );

        if ($this->supportsInteractiveButtons($tenantId)) {
            $this->sendButtons->execute(
                tenantId: $tenantId,
                contact: $contact,
                body: 'Gostou deste imóvel?',
                buttons: $this->buildButtons($property, $hasNext),
                conversation: $conversation,
            );
        }

        $context = $conversation->context ?? [];
        $context['catalog']['current_index'] = $index;
        $context['catalog']['confirmed'] = true;

        $conversation->update([
            'context' => $context,
        ]);

        $this->automationState->setPhase($conversation, ConversationAutomationPhase::Browsing);
    }

    /**
     * @return list<CatalogReplyButton>
     */
    private function buildButtons(PropertyModel $property, bool $hasNext): array
    {
        $buttons = [$this->formatter->visitButton($property)];

        if ($hasNext) {
            $buttons[] = $this->formatter->showMoreButton();
        }

        return $buttons;
    }

    private function supportsInteractiveButtons(string $tenantId): bool
    {
        if (! (bool) config('conversations.catalog.use_interactive_buttons', false)) {
            return false;
        }

        try {
            $config = $this->configResolver->resolveForTenant($tenantId);
        } catch (\Throwable) {
            return false;
        }

        return $config->provider === MessagingProvider::MetaCloud;
    }

    private function wasSent(MessageModel $message): bool
    {
        return $message->delivery_status === MessageDeliveryStatus::Sent;
    }
}
