<?php

declare(strict_types=1);

final class MyronPublicSearchRequestService
{
    public function __construct(private readonly MyronSearchIndexService $searchIndex)
    {
    }

    /** @return array<string, mixed> */
    public function search(string $query, int $limit = MyronSearchIndexService::DEFAULT_LIMIT, bool $includeExceptionDetails = false): array
    {
        $query = trim($query);
        if ($limit < 1) {
            $limit = MyronSearchIndexService::DEFAULT_LIMIT;
        }
        $limit = min($limit, MyronSearchIndexService::MAX_LIMIT);
        $result = [
            'query' => $query,
            'limit' => $limit,
            'results' => [],
            'total' => 0,
            'unavailable' => false,
            'transientError' => false,
            'exceptionDetails' => '',
            'state' => $query === '' ? 'empty-query' : 'no-results',
        ];
        if ($query === '') {
            return $result;
        }

        try {
            $payload = $this->searchIndex->query($query, ['limit' => $limit]);
            if (($payload['available'] ?? null) === false) {
                $result['unavailable'] = true;
                $result['state'] = 'unavailable';
                return $result;
            }
            $result['results'] = is_array($payload['results'] ?? null) ? array_values($payload['results']) : [];
            $result['total'] = (int) ($payload['total'] ?? 0);
            $result['state'] = $result['results'] === [] ? 'no-results' : 'results';
        } catch (Throwable $exception) {
            $result['transientError'] = true;
            $result['state'] = 'transient-error';
            error_log('[public-search] query failed: ' . $exception->getMessage());
            if ($includeExceptionDetails) {
                $result['exceptionDetails'] = get_class($exception) . ': ' . $exception->getMessage();
            }
        }
        return $result;
    }
}
