<?php

namespace Tests\Unit;

use App\Http\Controllers\Api\V1\MicrosoftAuthController;
use PHPUnit\Framework\TestCase;

/**
 * Guards the exact condition that closes the "nOAuth" account-takeover class
 * in multi-tenant Microsoft login (see MicrosoftAuthController::handleCallback):
 * a foreign tenant's admin can set a user's `mail` attribute to anyone's real
 * address with no domain-ownership check, so once other tenants are allowed
 * to sign in, an email match alone can never be trusted to mean "same person
 * as before" — only a match against the previously-bound Microsoft oid can.
 *
 * This one boolean expression is the whole defense. A refactor that drops the
 * !empty() guard would lock out every brand-new sign-up (no prior binding
 * yet, so nothing to compare against); a refactor that drops the oid
 * comparison reopens the takeover. Both are one-line regressions that would
 * be very easy to introduce accidentally and very hard to notice by reading
 * the code again — hence a dedicated test.
 */
class MicrosoftAuthSubjectMismatchTest extends TestCase
{
    public function test_brand_new_email_is_not_a_mismatch(): void
    {
        // No app-user row exists yet for this email at all.
        $this->assertFalse(MicrosoftAuthController::isSubjectMismatch(null, 'oid-123'));
    }

    public function test_existing_account_with_no_prior_binding_is_not_a_mismatch(): void
    {
        // Account created via password signup or before oid tracking existed
        // — must be allowed to bind on this login, not treated as a conflict.
        $existing = ['subject_id' => null];
        $this->assertFalse(MicrosoftAuthController::isSubjectMismatch($existing, 'oid-123'));

        $existingEmptyString = ['subject_id' => ''];
        $this->assertFalse(MicrosoftAuthController::isSubjectMismatch($existingEmptyString, 'oid-123'));
    }

    public function test_same_oid_repeat_login_is_not_a_mismatch(): void
    {
        $existing = ['subject_id' => 'oid-123'];
        $this->assertFalse(MicrosoftAuthController::isSubjectMismatch($existing, 'oid-123'));
    }

    public function test_different_oid_same_email_IS_a_mismatch(): void
    {
        // The actual attack: a foreign tenant's user claims an email that
        // already belongs to a different Microsoft identity.
        $existing = ['subject_id' => 'victim-real-oid'];
        $this->assertTrue(MicrosoftAuthController::isSubjectMismatch($existing, 'attacker-oid'));
    }

    public function test_null_incoming_oid_against_a_bound_account_is_a_mismatch(): void
    {
        // Defensive: if oid extraction ever fails and yields null, that must
        // not silently compare-equal against nothing and slip through.
        $existing = ['subject_id' => 'victim-real-oid'];
        $this->assertTrue(MicrosoftAuthController::isSubjectMismatch($existing, null));
    }
}
