<?php

namespace Tests\Feature\Api\V1\FullSurface;

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

class ApiRateLimitTokenAndSessionHardeningContractTest extends FullSurfaceE2EContractCase
{
    public function test_repeated_bad_login_attempts_stay_controlled_and_never_return_a_token(): void
    {
        $paths = array_values(array_unique(array_filter([
            '/api/v1/auth/login',
            '/api/login',
            '/api/v1/login',
        ], fn (string $path): bool => $this->routeExistsFor('POST', $path))));

        $this->assertNotEmpty($paths, 'At least one API login route should exist for brute-force hardening coverage.');

        foreach ($paths as $path) {
            for ($attempt = 1; $attempt <= 8; $attempt++) {
                $response = $this->postJson($path, [
                    'email' => $this->admin->email,
                    'password' => 'definitely-not-the-password-' . $attempt,
                ]);

                $this->assertStatusIn($response, [400, 401, 403, 419, 422, 429], "Bad login attempt {$attempt} for {$path}");
                $response->assertJsonMissingPath('token');
                $response->assertJsonMissingPath('access_token');
                $response->assertJsonMissingPath('user.remember_token');
            }
        }
    }

    public function test_expired_or_garbage_bearer_tokens_are_rejected_without_fallback_identity(): void
    {
        foreach ($this->apiRoutesContainingAny(['auth/me', 'dashboard', 'profile', 'settings', 'finance', 'inventory']) as $route) {
            $method = $this->primaryMethod($route);
            $uri = $route->uri();

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

            $response = $this->withHeader('Authorization', 'Bearer garbage-token-that-must-not-authenticate')
                ->json('GET', $this->materializePath($uri));

            $this->assertStatusIn($response, [401, 403, 404, 419], "Garbage bearer token should not authenticate {$uri}");
        }
    }

    public function test_logout_is_safe_to_repeat_and_does_not_leak_token_state(): void
    {
        $logoutRoutes = $this->apiRoutesContainingAny(['logout']);

        $this->assertNotEmpty($logoutRoutes, 'Logout routes should be covered by repeat/logout contract tests.');

        foreach ($logoutRoutes as $route) {
            if ($this->primaryMethod($route) !== 'POST') {
                continue;
            }

            $path = $this->materializePath($route->uri());

            $first = $this->requestAs($this->admin, 'POST', $route->uri());
            $this->assertControlled($first, 'POST', $route->uri());
            $first->assertJsonMissingPath('token');
            $first->assertJsonMissingPath('access_token');

            $second = $this->postJson($path);
            $this->assertStatusIn($second, [200, 204, 401, 403, 419], 'Repeated logout should stay controlled.');
            $second->assertJsonMissingPath('token');
            $second->assertJsonMissingPath('access_token');
        }
    }

    private function routeExistsFor(string $method, string $path): bool
    {
        foreach ($this->apiRoutes() as $route) {
            if ($this->primaryMethod($route) === $method && '/' . ltrim($route->uri(), '/') === $path) {
                return true;
            }
        }

        return false;
    }
}
