<?php

namespace Tests\Feature\Api\V1\FullSurface;

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

class ApiConcurrencyAndStaleWriteContractTest extends FullSurfaceE2EContractCase
{
    public function test_duplicate_update_payloads_remain_controlled_and_do_not_throw_server_errors(): void
    {
        foreach ($this->apiRoutesContainingAny(['profile', 'settings', 'attendance', 'inventory', 'payments', 'refunds', 'school-years', 'messages']) as $route) {
            $method = $this->primaryMethod($route);

            if (! in_array($method, ['PUT', 'PATCH', 'POST'], true)) {
                continue;
            }

            $payload = $this->payloadFor($method, $route->uri()) + [
                'client_request_id' => 'e2e-concurrency-' . md5($route->uri()),
                'updated_at' => '2000-01-01T00:00:00Z',
            ];

            $first = $this->requestAs($this->actorFor($route->uri()), $method, $route->uri(), $payload);
            $second = $this->requestAs($this->actorFor($route->uri()), $method, $route->uri(), $payload);

            $this->assertControlled($first, $method, $route->uri());
            $this->assertControlled($second, $method, $route->uri());
            $this->assertStringNotContainsString('deadlock', strtolower($second->getContent()));
            $this->assertStringNotContainsString('duplicate entry', strtolower($second->getContent()));
        }
    }

    public function test_stale_if_match_headers_do_not_force_successful_mutations(): void
    {
        foreach ($this->apiRoutesContainingAny(['students', 'parents', 'inventory', 'payments', 'attendance', 'settings']) as $route) {
            $method = $this->primaryMethod($route);

            if (! in_array($method, ['PUT', 'PATCH', 'DELETE'], true)) {
                continue;
            }

            $response = $this->actingAs($this->actorFor($route->uri()), 'api')
                ->withHeader('If-Match', '"stale-version-that-should-not-win"')
                ->json($method, $this->materializePath($route->uri()), $this->payloadFor($method, $route->uri()));

            $this->assertStatusIn($response, [200, 202, 204, 400, 403, 404, 409, 412, 422], "{$method} {$route->uri()} stale write");
        }
    }
}
