<?php

namespace Tests\Feature\Api\V1\FullSurface;

use Illuminate\Support\Facades\Route;
use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase;

class ApiOpenApiDocumentationDriftContractTest extends FullSurfaceE2EContractCase
{
    /** @test */
    public function api_surface_has_documentation_entry_points_and_route_inventory_remains_machine_readable(): void
    {
        $documentationRoutes = $this->apiRoutesContainingAny(['docs', 'documentation', 'openapi', 'swagger']);

        $this->assertNotEmpty($documentationRoutes, 'The API needs at least one documentation route. Tribal knowledge is not documentation, despite industry folklore.');

        foreach ($documentationRoutes as $route) {
            $response = $this->probeRoute($route);
            $this->assertControlled($response, $this->primaryMethod($route), $route->uri());
        }

        $apiRoutes = $this->apiRoutes();
        $this->assertGreaterThan(25, count($apiRoutes), 'The full-surface suite expects the application API route table to be loaded.');

        foreach ($apiRoutes as $route) {
            $this->assertNotEmpty($route->uri(), 'Every API route must have a URI. Revolutionary stuff.');
            $this->assertNotEmpty($route->methods(), 'Every API route must expose at least one method.');
        }
    }

    /** @test */
    public function named_api_routes_use_stable_names_when_names_exist(): void
    {
        foreach ($this->apiRoutes() as $route) {
            $name = $route->getName();

            if ($name === null) {
                continue;
            }

            $this->assertStringNotContainsString(' ', $name, "Route name [$name] should not contain spaces.");
            $this->assertStringNotContainsString('tmp', strtolower($name), "Route name [$name] looks temporary.");
            $this->assertStringNotContainsString('test', strtolower($name), "Route name [$name] looks like test scaffolding leaked into routing.");
        }
    }

    /** @test */
    public function documented_routes_do_not_point_to_missing_actions(): void
    {
        foreach (Route::getRoutes()->getRoutes() as $route) {
            if (! str_starts_with($route->uri(), 'api/')) {
                continue;
            }

            $action = $route->getActionName();
            $this->assertNotSame('Closure', $action, 'API routes should not depend on anonymous closures because documentation and traceability suffer.');
            $this->assertNotEmpty($action, 'API route action must be discoverable.');
        }
    }
}
