<?php

namespace App\Service\Search;

use Meilisearch\Client as MeilisearchClient;
use Meilisearch\Contracts\SearchQuery;

class Client
{
    private string $env;
    private MeilisearchClient $client;

    public function __construct(?MeilisearchClient $client = null)
    {
        // Récupération de l'environnement (ex: dev, prod)
        $this->env = $_ENV['APP_ENV'] ?? 'dev';

        // Connexion au serveur Meilisearch
        $this->client = $client ?? new MeilisearchClient(
            "https://tools-meilisearch.esy-web.dev",
            $_ENV['ESY_SEARCH_KEY'] ?? 'test_key'
        );
    }

    /**
     * Retourne la configuration centrale des index et de leurs filtres.
     */
    private function getIndexConfig(): array
    {
        return [
            "intranet_ludikevent_admin" => [],
            "intranet_ludikevent_customer" => [],
            "intranet_ludikevent_product" => [],
            "intranet_ludikevent_options" => [],
            "intranet_ludikevent_contrat" => [],

        ];
    }

    /**
     * Initialise les index avec préfixe et configure les attributs filtrables.
     */
    public function init(): void
    {
        $config = $this->getIndexConfig();

        foreach ($config as $indexName => $filterableAttributes) {
            $fullName = $this->env . "_" . $indexName;

            try {
                $this->client->createIndex($fullName, ['primaryKey' => 'id']);
            } catch (\Exception $e) {
                // L'index existe déjà
            }

            // Met à jour les réglages de filtrage
            $this->client->index($fullName)->updateFilterableAttributes($filterableAttributes);
        }
    }

    /**
     * Recherche globale dans TOUS les index configurés (Multi-search).
     * @param string $query Le terme recherché
     * @param int $limitPerIndex Nombre max de résultats par catégorie
     */
    public function searchGlobal(string $query, int $limitPerIndex = 5): array
    {
        $queries = [];
        $indexNames = array_keys($this->getIndexConfig());

        foreach ($indexNames as $indexName) {
            $searchQuery =new SearchQuery();
            $searchQuery->setQuery($query);
            $searchQuery->setLimit($limitPerIndex);
            $searchQuery->setIndexUid($this->env . "_" . $indexName);
            $queries[] = $searchQuery;
        }

        // Effectue une seule requête pour interroger tous les index
        return $this->client->multiSearch($queries);
    }

    /**
     * Recherche classique dans un index spécifique.
     */
    public function search(string $key, string $query, array $options = []): array
    {
        $fullName = $this->env . "_intranet_ludikevent_" . $key;
        return $this->client->index($fullName)->search($query, $options)->toArray();
    }

    /**
     * Ajoute ou met à jour des documents (Supporte un lot ou un document seul).
     */
    public function indexDocuments(array $documents, string $key): void
    {
        if (empty($documents)) return;

        $fullName = $this->env . "_intranet_ludikevent_" . $key;

        // Si on envoie un seul document (non-multidimensionnel)
        if (!isset($documents[0])) {
            $documents = [$documents];
        }

        $this->client->index($fullName)->addDocuments($documents);
    }

    /**
     * Récupère un document précis.
     */
    public function getDocument(string $key, $id): array
    {
        $fullName = $this->env . "_" . $key;
        return $this->client->index($fullName)->getDocument($id);
    }

    /**
     * Supprime un document par son ID.
     */
    public function deleteDocument(string $key, $id): void
    {
        $fullName = $this->env . "_" . $key;
        $this->client->index($fullName)->deleteDocument($id);
    }

    /**
     * Supprime un index complet.
     */
    public function deleteIndex(string $key): void
    {
        $fullName = $this->env . "_" . $key;
        $this->client->deleteIndex($fullName);
    }

    public function status() : bool
    {
        try {
            $result = $this->client->health();
            return  $result['status'] == "available";
        }catch (\Exception $e) {
            return false;
        }
    }
}
