<?php

namespace Tests\Feature\Api\V1\FullSurface;

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

class ApiMutationReadAfterWriteConsistencyContractTest extends FullSurfaceE2EContractCase
{
    public function test_created_resources_return_identifier_or_location_to_support_follow_up_reads(): void
    {
        foreach ($this->apiRoutes() as $route) {
            $method = $this->primaryMethod($route);

            if ($method !== 'POST') {
                continue;
            }

            $uri = $route->uri();

            if (str_contains($uri, 'logout') || str_contains($uri, 'login') || str_contains($uri, 'export') || str_contains($uri, 'download')) {
                continue;
            }

            $response = $this->requestAs($this->actorFor($uri), 'POST', $uri, $this->payloadFor('POST', $uri));
            $this->assertControlled($response, 'POST', $uri);

            if (! in_array($response->getStatusCode(), [200, 201, 202], true) || ! $this->isJsonString($response->getContent())) {
                continue;
            }

            $json = $response->json();
            $encoded = json_encode($json, JSON_THROW_ON_ERROR);

            $this->assertTrue(
                str_contains($encoded, '"id"') || str_contains($encoded, '"data"') || $response->headers->has('Location'),
                "POST {$uri} succeeded but returned no id/data/location for read-after-write follow-up."
            );
        }
    }

    public function test_update_successes_preserve_resource_identity_when_identity_is_present(): void
    {
        foreach ($this->apiRoutes() as $route) {
            $method = $this->primaryMethod($route);

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

            $uri = $route->uri();
            $response = $this->requestAs($this->actorFor($uri), $method, $uri, $this->payloadFor($method, $uri));
            $this->assertControlled($response, $method, $uri);

            if (! in_array($response->getStatusCode(), [200, 202], true) || ! $this->isJsonString($response->getContent())) {
                continue;
            }

            $body = $response->getContent();
            $this->assertStringNotContainsString('"id":null', $body, "{$method} {$uri} returned null id after successful update.");
        }
    }
}
