<?php

declare(strict_types=1);

namespace App\Framework\Search;

/**
 * Represents search results with metadata
 */
final readonly class SearchResult
{
    /**
     * @param SearchHit[] $hits
     * @param array<string, mixed> $aggregations
     */
    public function __construct(
        public array $hits,
        public int $total,
        public float $maxScore,
        public float $took, // in milliseconds
        public array $aggregations = [],
        public ?string $scrollId = null
    ) {
    }

    public function isEmpty(): bool
    {
        return empty($this->hits);
    }

    public function hasResults(): bool
    {
        return ! $this->isEmpty();
    }

    public function getHitCount(): int
    {
        return count($this->hits);
    }

    public function hasAggregations(): bool
    {
        return ! empty($this->aggregations);
    }

    public function getIds(): array
    {
        return array_map(fn ($hit) => $hit->id, $this->hits);
    }

    public function getDocuments(): array
    {
        return array_map(fn ($hit) => $hit->source, $this->hits);
    }

    public function getScores(): array
    {
        return array_map(fn ($hit) => $hit->score, $this->hits);
    }

    public function withScrollId(string $scrollId): self
    {
        return new self(
            $this->hits,
            $this->total,
            $this->maxScore,
            $this->took,
            $this->aggregations,
            $scrollId
        );
    }

    public function toArray(): array
    {
        return [
            'hits' => array_map(fn ($hit) => $hit->toArray(), $this->hits),
            'total' => $this->total,
            'max_score' => $this->maxScore,
            'took' => $this->took,
            'aggregations' => $this->aggregations,
            'scroll_id' => $this->scrollId,
        ];
    }
}
