<?php

declare(strict_types=1);

namespace ImovelZapAi\Conversations\Application\Services;

use ImovelZapAi\Conversations\Application\Data\ConversationSummaryContextData;
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\Data\PropertySearchFilters;

final class ConversationSummaryContextAssembler
{
    private const MESSAGE_LIMIT = 30;

    public function __construct(
        private readonly ConversationPropertyCodesQuery $propertyCodes,
    ) {}

    /**
     * @param  array<string, mixed>  $qualification
     */
    public function assemble(
        string $tenantId,
        ContactModel $contact,
        ConversationModel $conversation,
        array $qualification,
        bool $requestedVisit,
    ): ConversationSummaryContextData {
        /** @var list<string> $propertyIds */
        $propertyIds = $conversation->context['catalog']['property_ids'] ?? [];

        if (! is_array($propertyIds)) {
            $propertyIds = [];
        }

        $favoriteCodes = $this->propertyCodes->likedCodes(
            $tenantId,
            (string) $contact->id,
            (string) $conversation->id,
            $propertyIds,
        );

        $presentedCodes = array_values(array_unique([
            ...$this->propertyCodes->presentedCodes($tenantId, $propertyIds),
            ...$favoriteCodes,
        ]));

        return new ConversationSummaryContextData(
            tenantId: $tenantId,
            conversationId: (string) $conversation->id,
            clientName: trim((string) ($contact->display_name ?: $contact->phone ?: 'Cliente')),
            search: $this->searchFromConversation($conversation),
            qualification: $qualification,
            presentedPropertyCodes: $presentedCodes,
            favoritePropertyCodes: $favoriteCodes,
            requestedVisit: $requestedVisit,
            messageExcerpts: $this->messageExcerpts($conversation),
        );
    }

    private function searchFromConversation(ConversationModel $conversation): PropertySearchFilters
    {
        $raw = $conversation->context['catalog']['filters']
            ?? $conversation->context['search']['pending_filters']
            ?? [];

        if (! is_array($raw) || $raw === []) {
            return new PropertySearchFilters;
        }

        return PropertySearchFilters::fromQueryArray($raw);
    }

    /**
     * @return list<string>
     */
    private function messageExcerpts(ConversationModel $conversation): array
    {
        return MessageModel::query()
            ->where('conversation_id', $conversation->id)
            ->whereNotNull('body')
            ->where('body', '!=', '')
            ->orderBy('created_at')
            ->limit(self::MESSAGE_LIMIT)
            ->get()
            ->map(function (MessageModel $message): string {
                $speaker = $message->direction->value === 'inbound' ? 'Cliente' : 'Assistente';

                return $speaker.': '.trim((string) $message->body);
            })
            ->values()
            ->all();
    }
}
