<?php

namespace Tests\Feature\Api\V1\FullSurface;

use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase;

class ApiSearchIndexAndAutocompleteContractTest extends FullSurfaceE2EContractCase
{
    public function test_search_autocomplete_and_lookup_routes_handle_empty_short_and_hostile_terms(): void
    {
        $routes = $this->apiRoutesContainingAny(['search', 'lookup', 'autocomplete', 'suggest', 'filter']);
        $terms = ['', 'a', '   ', '%', "' OR '1'='1", '<script>alert(1)</script>', str_repeat('x', 2048)];

        foreach ($routes as $route) {
            $method = $this->primaryMethod($route);
            if ($method !== 'GET') {
                continue;
            }

            $uri = $route->uri();
            foreach ($terms as $term) {
                $response = $this->requestAs($this->actorFor($uri), 'GET', $uri . '?q=' . urlencode($term) . '&term=' . urlencode($term) . '&search=' . urlencode($term));
                $this->assertNoServerError($response, "GET $uri search term $term");
                $this->assertControlled($response, 'GET', $uri);
                $this->assertStringNotContainsStringIgnoringCase('SQLSTATE', $response->getContent(), $uri . ' should not leak SQLSTATE from search.');
                $this->assertStringNotContainsString('<script>alert(1)</script>', $response->getContent(), $uri . ' should not reflect raw script search terms.');
            }
        }
    }

    public function test_cross_domain_search_does_not_bypass_role_scope(): void
    {
        $routes = $this->apiRoutesContainingAny(['search', 'lookup', 'autocomplete']);

        foreach ($routes as $route) {
            if ($this->primaryMethod($route) !== 'GET') {
                continue;
            }

            $uri = $route->uri();
            $query = '?q=*&scope=all&include=users,parents,students,finance,medical';

            foreach (['parent' => $this->parent, 'teacher' => $this->teacher, 'student' => $this->studentUser] as $label => $actor) {
                $response = $this->requestAs($actor, 'GET', $uri . $query);
                $this->assertNoServerError($response, "$label GET $uri broad search");
                $this->assertStatusIn($response, [200, 204, 302, 400, 401, 403, 404, 409, 419, 422], "$label GET $uri broad search");
                $this->assertStringNotContainsStringIgnoringCase('remember_token', $response->getContent(), "$uri broad search must not leak auth internals.");
            }
        }
    }
}
