<?php

namespace Tests\Feature\Api\V1\FullSurface;

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

class ApiOperationalResiliencePayloadSizeContractTest extends FullSurfaceE2EContractCase
{
    public function test_mutating_routes_reject_huge_payloads_and_deep_arrays_without_memory_or_server_errors(): void
    {
        $routes = array_slice(array_filter($this->apiRoutes(), function ($route): bool {
            return in_array($this->primaryMethod($route), ['POST', 'PUT', 'PATCH'], true);
        }), 0, 120);

        $payload = [
            'name' => str_repeat('A', 10000),
            'description' => str_repeat('B', 50000),
            'notes' => str_repeat('C', 50000),
            'nested' => array_fill(0, 50, ['x' => str_repeat('D', 1000)]),
            'ids' => range(1, 2000),
        ];

        foreach ($routes as $route) {
            $method = $this->primaryMethod($route);
            $uri = $route->uri();
            $response = $this->requestAs($this->actorFor($uri), $method, $uri, $this->payloadFor($method, $uri) + $payload);

            $this->assertNoServerError($response, "$method $uri huge payload");
            $this->assertControlled($response, $method, $uri);
            $this->assertStringNotContainsStringIgnoringCase('Allowed memory size', $response->getContent(), $uri . ' should not leak memory exhaustion.');
        }
    }

    public function test_get_routes_reject_abusive_include_expand_and_field_lists_cleanly(): void
    {
        foreach (array_slice($this->apiRoutes(), 0, 150) as $route) {
            if ($this->primaryMethod($route) !== 'GET') {
                continue;
            }

            $uri = $route->uri();
            $query = '?include=' . urlencode(str_repeat('parents.students.invoices.payments.', 100))
                . '&fields=' . urlencode(str_repeat('id,email,password,remember_token,', 200))
                . '&expand=' . urlencode(str_repeat('children.', 200));

            $response = $this->requestAs($this->actorFor($uri), 'GET', $uri . $query);
            $this->assertNoServerError($response, "GET $uri abusive expansion query");
            $this->assertControlled($response, 'GET', $uri);
        }
    }
}
