<?php

declare(strict_types=1);

namespace ImovelZapAi\Conversations\Application\Queries;

use Illuminate\Support\Collection;
use ImovelZapAi\Conversations\Application\Data\ConversationPropertyBriefData;
use ImovelZapAi\Conversations\Application\Services\PropertyBriefBuilder;
use ImovelZapAi\Conversations\Infrastructure\Persistence\Eloquent\ConversationModel;
use ImovelZapAi\Properties\Infrastructure\Persistence\Eloquent\PropertyInterestModel;
use ImovelZapAi\Properties\Infrastructure\Persistence\Eloquent\PropertyModel;

final class ConversationPropertiesQuery
{
    public function __construct(
        private readonly PropertyBriefBuilder $briefBuilder,
    ) {}

    /**
     * @return Collection<int, ConversationPropertyBriefData>
     */
    public function forConversation(
        string $tenantId,
        string $contactId,
        ConversationModel $conversation,
    ): Collection {
        $favoriteIds = PropertyInterestModel::query()
            ->where('tenant_id', $tenantId)
            ->where('contact_id', $contactId)
            ->where('conversation_id', $conversation->id)
            ->pluck('property_id')
            ->map(fn ($id): string => (string) $id)
            ->values()
            ->all();

        $catalogIds = $this->catalogPropertyIds($conversation);
        $orderedIds = array_values(array_unique([...$favoriteIds, ...$catalogIds]));

        if ($orderedIds === []) {
            return collect();
        }

        $properties = PropertyModel::query()
            ->where('tenant_id', $tenantId)
            ->whereIn('id', $orderedIds)
            ->with(['neighborhood', 'city', 'images'])
            ->get()
            ->keyBy('id');

        return collect($orderedIds)
            ->map(fn (string $id) => $properties->get($id))
            ->filter()
            ->map(fn (PropertyModel $property): ConversationPropertyBriefData => $this->briefBuilder->fromModel(
                $property,
                in_array((string) $property->id, $favoriteIds, true),
            ))
            ->values();
    }

    /**
     * @return list<string>
     */
    private function catalogPropertyIds(ConversationModel $conversation): array
    {
        $context = $conversation->context ?? [];
        $catalog = is_array($context['catalog'] ?? null) ? $context['catalog'] : [];

        /** @var list<string> $ids */
        $ids = is_array($catalog['property_ids'] ?? null) ? $catalog['property_ids'] : [];

        $currentIndex = $catalog['current_index'] ?? null;

        if (is_int($currentIndex) || is_string($currentIndex)) {
            $index = (int) $currentIndex;
            $currentId = $ids[$index] ?? null;

            if (is_string($currentId) && $currentId !== '' && ! in_array($currentId, $ids, true)) {
                $ids[] = $currentId;
            }
        }

        return array_values(array_filter($ids, static fn (mixed $id): bool => is_string($id) && $id !== ''));
    }
}
