<?php

declare(strict_types=1);

namespace Apexl\Tests\User\FeatureTests;

use apexl\Io\modules\user\entities\userEntity;
use apexl\Io\modules\user\services\CurrentUserFactory;
use apexl\Io\TestInfrastructure\FeatureTest;
use PHPUnit\Framework\Attributes\Test;
use function apexl\Io\container;

/**
 * `created_by` is stamped by AddCreatedByToEntitiesOnSave on HOOK__BEFORE_FIRST_STORE.
 *
 * A FeatureTest, not a UnitTest: the hook is registered by userModule, and this
 * asserts on the row that actually lands in the database — the defect it covers
 * lived in Entity::callHooks(), which handed the second hook the ORIGINAL input
 * instead of the first hook's result, so this hook's work was discarded for
 * every insert between 20 Jan 2026 and apexl/io 3.10.7.
 */
final class CreatedByIsStampedOnFirstStoreTest extends FeatureTest
{
    private function newUser(): userEntity
    {
        $user = new userEntity();
        $user->first_name = 'Created';
        $user->last_name = 'By';
        $user->email = 'created-by-' . bin2hex(random_bytes(6)) . '@example.com';
        $user->password = 'irrelevant';
        $user->salt = 'irrelevant';

        return $user;
    }

    /** getField(), not the magic accessor — `created_by` casts to a userEntity. */
    private function storedCreatedBy(userEntity $user): mixed
    {
        return userEntity::find((int) $user->id)->getField('created_by');
    }

    #[Test]
    public function firstStoreStampsTheCurrentUser(): void
    {
        $currentUserId = container()->get(CurrentUserFactory::class)->get()?->id;
        $this->assertNotNull($currentUserId, 'The spoofed global user must exist for this test to mean anything.');

        $user = $this->newUser();
        $user->store();

        $this->assertSame((int) $currentUserId, (int) $this->storedCreatedBy($user));
    }

    #[Test]
    public function anExplicitlyAssignedCreatedBySurvivesTheHook(): void
    {
        // First-write-wins: provenance set by the caller is not the framework's
        // to overwrite. Regression cover for the guard restored in io-user 3.10.0.
        $user = $this->newUser();
        $user->created_by = 4242;
        $user->store();

        $this->assertSame(4242, (int) $this->storedCreatedBy($user));
    }
}
