<?php

declare(strict_types=1);

namespace Apexl\Tests\User\FeatureTests;

use apexl\Io\includes\RouteManager;
use apexl\Io\modules\user\entities\userEntity;
use apexl\Io\TestInfrastructure\FeatureTest;
use PHPUnit\Framework\Attributes\Test;

use function apexl\Io\container;

/**
 * Account-enumeration guard: the forgot-password submission must respond
 * identically whether or not the submitted email belongs to a real account,
 * so an anonymous visitor can't use it to probe which addresses are
 * registered. Both branches resolve to the same check-email redirect with
 * no distinguishing message added (see ForgotPasswordController).
 */
final class ForgotPasswordTest extends FeatureTest
{
    #[Test]
    public function knownEmailRedirectsToCheckEmail(): void
    {
        $user = userEntity::factory()->create();

        $data = $this->post('/api/v1/user/action/forgot-password', [
            'email' => $user->email,
        ]);

        $this->assertResponseShape($data);
    }

    #[Test]
    public function unknownEmailRedirectsToCheckEmail(): void
    {
        $data = $this->post('/api/v1/user/action/forgot-password', [
            'email' => $this->faker->unique()->safeEmail(),
        ]);

        $this->assertResponseShape($data);
    }

    #[Test]
    public function knownAndUnknownEmailResponsesAreIndistinguishable(): void
    {
        $user = userEntity::factory()->create();

        $known = $this->post('/api/v1/user/action/forgot-password', [
            'email' => $user->email,
        ]);

        $unknown = $this->post('/api/v1/user/action/forgot-password', [
            'email' => $this->faker->unique()->safeEmail(),
        ]);

        // Same shape/class of response: same keys, no error message on
        // either branch, identical redirect target. This is the actual
        // enumeration-leak regression check -- previously the unknown-email
        // branch omitted the redirect key entirely and added a 'messages'
        // key with 'User account does not exist', which is trivially
        // distinguishable from the known-email response.
        $this->assertSame(array_keys($known), array_keys($unknown));
        $this->assertArrayNotHasKey('messages', $known);
        $this->assertArrayNotHasKey('messages', $unknown);
        $this->assertSame($known['redirect'], $unknown['redirect']);
        $this->assertSame($known['success'], $unknown['success']);
    }

    private function assertResponseShape(array $data): void
    {
        $this->assertTrue($data['success']);
        $this->assertArrayNotHasKey('messages', $data);
        $this->assertSame(
            container()->get(RouteManager::class)->getRoutePattern('user.display.forgot-password.check-email'),
            $data['redirect'],
        );
    }
}
