<?php

declare(strict_types=1);

namespace App\Tests\Functional\Administration\Api;

use ApiPlatform\Symfony\Bundle\Test\ApiTestCase;
use PHPUnit\Framework\Attributes\Test;

/**
 * Tests that password reset endpoints are accessible without authentication.
 *
 * These endpoints MUST be public because users who forgot their password
 * cannot authenticate to request a reset.
 */
final class PasswordResetEndpointsTest extends ApiTestCase
{
    /**
     * Opt-in for API Platform 5.0 behavior where kernel boot is explicit.
     *
     * @see https://github.com/api-platform/core/issues/6971
     */
    protected static ?bool $alwaysBootKernel = true;

    #[Test]
    public function passwordForgotEndpointIsAccessibleWithoutAuthentication(): void
    {
        $client = static::createClient();

        $response = $client->request('POST', '/api/password/forgot', [
            'json' => ['email' => 'test@example.com'],
            'headers' => [
                'Host' => 'localhost',
            ],
        ]);

        // Should NOT return 401 Unauthorized
        // It should return 200 (success) or 429 (rate limited), but never 401
        self::assertNotEquals(401, $response->getStatusCode(), 'Password forgot endpoint should be accessible without JWT');

        // The endpoint always returns success to prevent email enumeration
        // Even for non-existent emails
        self::assertResponseIsSuccessful();
    }

    #[Test]
    public function passwordResetEndpointIsAccessibleWithoutAuthentication(): void
    {
        $client = static::createClient();

        $response = $client->request('POST', '/api/password/reset', [
            'json' => [
                'token' => 'invalid-token-for-test',
                'password' => 'NewSecurePassword123!',
            ],
            'headers' => [
                'Host' => 'localhost',
            ],
        ]);

        // Should NOT return 401 Unauthorized
        // It should return 400 (invalid token) or 410 (expired), but never 401
        self::assertNotEquals(401, $response->getStatusCode(), 'Password reset endpoint should be accessible without JWT');

        // With an invalid token, we expect a 400 Bad Request
        self::assertResponseStatusCodeSame(400);
    }

    #[Test]
    public function passwordForgotValidatesEmailFormat(): void
    {
        $client = static::createClient();

        $response = $client->request('POST', '/api/password/forgot', [
            'json' => ['email' => 'not-an-email'],
            'headers' => [
                'Host' => 'localhost',
            ],
        ]);

        // Invalid email format returns validation error (422)
        // This is acceptable because it doesn't reveal user existence
        // (format validation happens before checking if user exists)
        self::assertResponseStatusCodeSame(422);
    }

    #[Test]
    public function passwordResetValidatesPasswordRequirements(): void
    {
        $client = static::createClient();

        // Password too short
        $response = $client->request('POST', '/api/password/reset', [
            'json' => [
                'token' => 'some-token',
                'password' => 'short',
            ],
            'headers' => [
                'Host' => 'localhost',
            ],
        ]);

        // Should return 422 Unprocessable Entity for validation errors
        self::assertResponseStatusCodeSame(422);
    }
}
