<?php

namespace Tests\Feature\Api\V1\FullSurface;

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

class ApiContentNegotiationAndMediaTypeContractTest extends FullSurfaceE2EContractCase
{
    /** @test */
    public function json_accept_header_receives_controlled_api_responses_across_major_domains(): void
    {
        $routes = array_slice($this->apiRoutesContainingAny([
            'auth', 'users', 'students', 'parents', 'teacher', 'attendance', 'finance', 'inventory', 'messages', 'settings',
        ]), 0, 80);

        foreach ($routes as $route) {
            $method = $this->primaryMethod($route);
            $uri = $route->uri();

            $this->actingAs($this->actorFor($uri), 'api');
            $response = $this->withHeaders(['Accept' => 'application/json'])->json($method, $this->materializePath($uri), $this->payloadFor($method, $uri));

            $this->assertControlled($response, $method, $uri);
            $this->assertJsonResponseWhenSuccessful($response, "$method $uri with JSON Accept");
        }
    }

    /** @test */
    public function unsupported_accept_headers_do_not_trigger_server_errors(): void
    {
        foreach (array_slice($this->apiRoutes(), 0, 60) as $route) {
            $method = $this->primaryMethod($route);
            $uri = $route->uri();

            $this->actingAs($this->actorFor($uri), 'api');
            $response = $this->withHeaders(['Accept' => 'application/xml'])->json($method, $this->materializePath($uri), $this->payloadFor($method, $uri));

            $this->assertStatusIn($response, [200, 201, 202, 204, 302, 304, 400, 401, 403, 404, 405, 406, 409, 415, 419, 422], "$method $uri unsupported Accept");
        }
    }

    /** @test */
    public function malformed_content_type_for_mutations_fails_cleanly(): void
    {
        $routes = array_slice(array_filter($this->apiRoutes(), fn ($route) => in_array($this->primaryMethod($route), ['POST', 'PUT', 'PATCH'], true)), 0, 70);

        foreach ($routes as $route) {
            $method = $this->primaryMethod($route);
            $uri = $route->uri();

            $this->actingAs($this->actorFor($uri), 'api');
            $response = $this->withHeaders([
                'Accept' => 'application/json',
                'Content-Type' => 'text/plain',
            ])->call($method, $this->materializePath($uri), [], [], [], [], 'not-json=not-really');

            $this->assertStatusIn($response, [200, 201, 202, 204, 400, 401, 403, 404, 405, 409, 415, 419, 422], "$method $uri malformed content type");
            $this->assertLessThan(500, $response->getStatusCode(), "$method $uri should not explode on plain text bodies.");
        }
    }
}
