<?php

namespace App\Http\Controllers;

use App\Services\MeilisearchService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class MeilisearchSettingsController extends Controller
{
    public function __construct(private MeilisearchService $meilisearch)
    {
    }

    public function getTypoTolerance(): JsonResponse
    {
        if (!$this->meilisearch->isEnabled()) {
            return response()->json(
                ['message' => 'Meilisearch is not enabled for this tenant.'],
                400
            );
        }

        $typoTolerance = $this->meilisearch->getVehicleIndex()->getTypoTolerance();

        return response()->json($typoTolerance);
    }

    public function updateTypoTolerance(Request $request): JsonResponse
    {
        if (!$this->meilisearch->isEnabled()) {
            return response()->json(
                ['message' => 'Meilisearch is not enabled for this tenant.'],
                400
            );
        }

        $validated = $request->validate([
            'enabled' => 'required|boolean',
            'minWordSizeForTypos.oneTypo' => 'required|integer|min:1',
            'minWordSizeForTypos.twoTypos' => 'required|integer|min:1',
            'disableOnWords' => 'array',
            'disableOnWords.*' => 'string',
            'disableOnAttributes' => 'array',
            'disableOnAttributes.*' => 'string',
        ]);

        $this->meilisearch->getVehicleIndex()->updateTypoTolerance($validated);

        $typoTolerance = $this->meilisearch->getVehicleIndex()->getTypoTolerance();

        return response()->json($typoTolerance);
    }

    public function getStopWords(): JsonResponse
    {
        if (!$this->meilisearch->isEnabled()) {
            return response()->json(
                ['message' => 'Meilisearch is not enabled for this tenant.'],
                400
            );
        }

        $stopWords = $this->meilisearch->getVehicleIndex()->getStopWords();

        return response()->json($stopWords);
    }

    public function updateStopWords(Request $request): JsonResponse
    {
        if (!$this->meilisearch->isEnabled()) {
            return response()->json(
                ['message' => 'Meilisearch is not enabled for this tenant.'],
                400
            );
        }

        $validated = $request->validate([
            'words' => 'array',
            'words.*' => 'string',
        ]);

        $this->meilisearch->getVehicleIndex()->updateStopWords($validated['words'] ?? []);

        $stopWords = $this->meilisearch->getVehicleIndex()->getStopWords();

        return response()->json($stopWords);
    }

    public function getRankingRules(): JsonResponse
    {
        if (!$this->meilisearch->isEnabled()) {
            return response()->json(
                ['message' => 'Meilisearch is not enabled for this tenant.'],
                400
            );
        }

        $rankingRules = $this->meilisearch->getVehicleIndex()->getRankingRules();

        return response()->json($rankingRules);
    }

    public function updateRankingRules(Request $request): JsonResponse
    {
        if (!$this->meilisearch->isEnabled()) {
            return response()->json(
                ['message' => 'Meilisearch is not enabled for this tenant.'],
                400
            );
        }

        $validated = $request->validate([
            'rules' => 'required|array',
            'rules.*' => 'string',
        ]);

        $this->meilisearch->getVehicleIndex()->updateRankingRules($validated['rules']);

        $rankingRules = $this->meilisearch->getVehicleIndex()->getRankingRules();

        return response()->json($rankingRules);
    }

    public function getSearchableAttributes(): JsonResponse
    {
        if (!$this->meilisearch->isEnabled()) {
            return response()->json(
                ['message' => 'Meilisearch is not enabled for this tenant.'],
                400
            );
        }

        $attributes = $this->meilisearch->getVehicleIndex()->getSearchableAttributes();

        return response()->json($attributes);
    }

    public function updateSearchableAttributes(Request $request): JsonResponse
    {
        if (!$this->meilisearch->isEnabled()) {
            return response()->json(
                ['message' => 'Meilisearch is not enabled for this tenant.'],
                400
            );
        }

        $validated = $request->validate([
            'attributes' => 'required|array',
            'attributes.*' => 'string',
        ]);

        $this->meilisearch->getVehicleIndex()->updateSearchableAttributes(
            $validated['attributes']
        );

        $attributes = $this->meilisearch->getVehicleIndex()->getSearchableAttributes();

        return response()->json($attributes);
    }

    public function getFaceting(): JsonResponse
    {
        if (!$this->meilisearch->isEnabled()) {
            return response()->json(
                ['message' => 'Meilisearch is not enabled for this tenant.'],
                400
            );
        }

        $faceting = $this->meilisearch->getVehicleIndex()->getFaceting();

        return response()->json($faceting);
    }

    public function updateFaceting(Request $request): JsonResponse
    {
        if (!$this->meilisearch->isEnabled()) {
            return response()->json(
                ['message' => 'Meilisearch is not enabled for this tenant.'],
                400
            );
        }

        $validated = $request->validate([
            'maxValuesPerFacet' => 'required|integer|min:1|max:10000',
        ]);

        $this->meilisearch->getVehicleIndex()->updateFaceting($validated);

        $faceting = $this->meilisearch->getVehicleIndex()->getFaceting();

        return response()->json($faceting);
    }

    public function search(Request $request): JsonResponse
    {
        if (!$this->meilisearch->isEnabled()) {
            return response()->json(
                ['message' => 'Meilisearch is not enabled for this tenant.'],
                400
            );
        }

        $validated = $request->validate([
            'query' => 'required|string|max:200',
            'limit' => 'sometimes|integer|min:1|max:50',
        ]);

        $results = $this->meilisearch->getVehicleIndex()->search(
            $validated['query'],
            [
                'limit' => $validated['limit'] ?? 20,
                'attributesToHighlight' => ['*'],
                'highlightPreTag' => '<mark>',
                'highlightPostTag' => '</mark>',
                'showMatchesPosition' => true,
            ]
        );

        return response()->json([
            'hits' => $results->getHits(),
            'query' => $results->getQuery(),
            'processingTimeMs' => $results->getProcessingTimeMs(),
            'estimatedTotalHits' => $results->getEstimatedTotalHits(),
        ]);
    }
}
