<?php

namespace Tests\Feature\Api\V1\FullSurface;

use Illuminate\Routing\Route as LaravelRoute;
use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase;

class ApiDeepResponseShapeAndEnvelopeContractTest extends FullSurfaceE2EContractCase
{
    public function test_successful_json_api_responses_use_parseable_json_envelopes_across_major_domains(): void
    {
        $failures = [];

        foreach ($this->representativeDomainRoutes() as $route) {
            $method = $this->primaryMethod($route);
            $uri = $route->uri();
            $response = $this->probeRoute($route);
            $status = $response->getStatusCode();

            if ($status >= 500) {
                $failures[] = "$method $uri crashed with $status: " . $response->getContent();
                continue;
            }

            if ($status >= 200 && $status < 300 && $response->getContent() !== '' && ! $this->isJsonString($response->getContent())) {
                $failures[] = "$method $uri returned non-json successful API response: " . $response->getContent();
            }
        }

        $this->assertSame([], $failures, "Successful API responses should be machine-readable JSON:\n" . implode("\n", $failures));
    }

    public function test_collection_endpoints_expose_list_like_payloads_or_explicit_empty_state(): void
    {
        $failures = [];

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

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

            $response = $this->probeRoute($route);
            $status = $response->getStatusCode();

            if (! in_array($status, [200, 204, 302, 401, 403, 404, 422], true)) {
                $failures[] = "$method $uri returned unexpected $status for collection contract: " . $response->getContent();
                continue;
            }

            if ($status === 200 && $this->isJsonString($response->getContent())) {
                $payload = $response->json();
                $hasCollectionShape = is_array($payload)
                    && (array_is_list($payload)
                        || array_key_exists('data', $payload)
                        || array_key_exists('items', $payload)
                        || array_key_exists('results', $payload)
                        || array_key_exists('rows', $payload)
                        || array_key_exists('ok', $payload)
                        || array_key_exists('status', $payload));

                if (! $hasCollectionShape) {
                    $failures[] = "$method $uri returned JSON but no recognizable collection/envelope keys: " . $response->getContent();
                }
            }
        }

        $this->assertSame([], $failures, "Collection routes need a stable list/envelope shape:\n" . implode("\n", $failures));
    }

    /** @return list<LaravelRoute> */
    private function representativeDomainRoutes(): array
    {
        return array_slice($this->apiRoutesContainingAny([
            'auth', 'administrator', 'teachers', 'parents', 'students', 'attendance', 'scores',
            'finance', 'inventory', 'messages', 'support', 'settings', 'school-years', 'families',
        ]), 0, 120);
    }

    /** @return list<LaravelRoute> */
    private function collectionLikeRoutes(): array
    {
        return array_values(array_filter($this->apiRoutes(), function (LaravelRoute $route): bool {
            if ($this->primaryMethod($route) !== 'GET') {
                return false;
            }

            $uri = $route->uri();

            return ! preg_match('#/\{[^}]+\}$#', $uri)
                && ! str_contains($uri, 'download')
                && ! str_contains($uri, 'export')
                && ! str_contains($uri, 'print')
                && ! str_contains($uri, 'pdf');
        }));
    }
}
