<?php

use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ObjectType;
use App\GraphQL\Types\JsonType;

$gql->queries['fields']['detektivoSearch'] = [

    'type' => new ObjectType([
        'name'   => 'DetektivoSearchResult',
        'fields' =>  [
            'hits' => Type::listOf(JsonType::instance()),
            'query' => Type::string(),
            'processingTimeMs' => Type::int(),
            'limit' => Type::int(),
            'offset' => Type::int(),
            'estimatedTotalHits' => Type::int(),
            'facets' => JsonType::instance(),
        ]
    ]),

    'args' => [

        'index'  => Type::nonNull(Type::string()),
        'limit' => ['type' => Type::int(), 'defaultValue' => 50],
        'offset'  => ['type' => Type::int(), 'defaultValue' => 0],
        'q'  => ['type' => Type::string(), 'defaultValue' => ''],
        'fields' => ['type' => Type::string(), 'defaultValue' => '*'],
        'filter' => ['type' => JsonType::instance(), 'defaultValue' => null],
        
        // Fuzzy search parameters
        'fuzzy' => ['type' => Type::boolean(), 'defaultValue' => null],
        'fuzzyAlgorithm' => ['type' => Type::string(), 'defaultValue' => null],
        'fuzzyThreshold' => ['type' => Type::float(), 'defaultValue' => null],
        'fuzzyMinScore' => ['type' => Type::float(), 'defaultValue' => null],
        'typoTolerance' => ['type' => Type::boolean(), 'defaultValue' => null],
        'rankingScoreThreshold' => ['type' => Type::float(), 'defaultValue' => null],
        'highlights' => ['type' => Type::boolean(), 'defaultValue' => null],
        'attributesToHighlight' => ['type' => Type::listOf(Type::string()), 'defaultValue' => null],
        // Facets & boosts
        'facets' => ['type' => Type::listOf(Type::string()), 'defaultValue' => null],
        'facetLimit' => ['type' => Type::int(), 'defaultValue' => null],
        'facetOffset' => ['type' => Type::int(), 'defaultValue' => null],
        'boosts' => ['type' => JsonType::instance(), 'defaultValue' => null],
    ],

    'resolve' => function ($root, $args) use($app) {

        $index = $args['index'];

        if (!$app->helper('acl')->isAllowed('detektivo/api/search', $app->helper('auth')->getUser('role'))) {
            $app->response->status = 403;
            return [];
        }

        if (!$app->module('detektivo')->exists($index)) {
            return [];
        }

        $idx = $app->module('detektivo')->index($index);
        $query = $args['q'];

        if (!trim($query)) {
            $app->response->status = 412;
            return ['error' => 'Query parameter is missing or empty!'];
        }
        
        // Validate fuzzy search parameters
        if ($args['fuzzyAlgorithm'] !== null) {
            $validAlgorithms = ['levenshtein', 'jaro_winkler', 'trigram', 'soundex', 'hybrid', 'fts5'];
            if (!in_array($args['fuzzyAlgorithm'], $validAlgorithms)) {
                return ['error' => 'Invalid fuzzy_algorithm. Must be one of: ' . implode(', ', $validAlgorithms)];
            }
        }
        
        if ($args['fuzzyThreshold'] !== null && ($args['fuzzyThreshold'] < 0.0 || $args['fuzzyThreshold'] > 1.0)) {
            return ['error' => 'fuzzy_threshold must be between 0.0 and 1.0'];
        }
        
        if ($args['fuzzyMinScore'] !== null && ($args['fuzzyMinScore'] < 0.0 || $args['fuzzyMinScore'] > 1.0)) {
            return ['error' => 'fuzzy_min_score must be between 0.0 and 1.0'];
        }
        
        if ($args['rankingScoreThreshold'] !== null && ($args['rankingScoreThreshold'] < 0.0 || $args['rankingScoreThreshold'] > 1.0)) {
            return ['error' => 'ranking_score_threshold must be between 0.0 and 1.0'];
        }

        $params = [
            'limit' => $args['limit'],
            'offset' => $args['offset'],
            'fields' => $args['fields'],
        ];

        // Add optional parameters if provided
        if ($args['filter'] !== null) {
            $params['filter'] = $args['filter'];
        }
        
        // Add fuzzy search parameters if provided
        if ($args['fuzzy'] !== null) {
            $params['fuzzy'] = $args['fuzzy'];
        }
        
        if ($args['fuzzyAlgorithm'] !== null) {
            $params['fuzzy_algorithm'] = $args['fuzzyAlgorithm'];
        }
        
        if ($args['fuzzyThreshold'] !== null) {
            $params['fuzzy_threshold'] = $args['fuzzyThreshold'];
        }
        
        if ($args['fuzzyMinScore'] !== null) {
            $params['fuzzy_min_score'] = $args['fuzzyMinScore'];
        }
        
        if ($args['typoTolerance'] !== null) {
            $params['typoTolerance'] = $args['typoTolerance'];
        }
        
        if ($args['rankingScoreThreshold'] !== null) {
            $params['rankingScoreThreshold'] = $args['rankingScoreThreshold'];
        }
        
        if ($args['highlights'] !== null) {
            $params['highlights'] = $args['highlights'];
        }
        
        if ($args['attributesToHighlight'] !== null) {
            $params['attributesToHighlight'] = $args['attributesToHighlight'];
        }

        // Facets
        if (!empty($args['facets'])) {
            $params['facets'] = $args['facets'];
            if ($args['facetLimit'] !== null) $params['facet_limit'] = (int)$args['facetLimit'];
            if ($args['facetOffset'] !== null) $params['facet_offset'] = (int)$args['facetOffset'];
        }

        // Boosts
        if (!empty($args['boosts']) && is_array($args['boosts'])) {
            $params['boosts'] = $args['boosts'];
        }

        return $idx->search($query, $params);
    }
];
