<?php

declare(strict_types=1);

namespace Apexl\Tests\User\Helpers;

use apexl\Config\Configuration;
use apexl\Config\ConfigurationInterface;
use ReflectionProperty;
use function apexl\Io\container;

/**
 * Test helper: override `auth.two_factor.*` config at runtime. The config file
 * is loaded + locked at bootstrap, so this reaches into the shared
 * Configuration's flat map via reflection and restores it afterwards. Call
 * restoreTwoFactorConfig() in tearDown().
 */
trait ManagesTwoFactorConfig
{
    /** @var array<string, mixed> */
    private array $originalTwoFactorConfig = [];

    private bool $twoFactorConfigCaptured = false;

    protected function setTwoFactorMode(string $mode): void
    {
        $this->setTwoFactorConfig(['auth.two_factor.mode' => $mode]);
    }

    /**
     * @param array<string, mixed> $overrides flat keys, e.g. 'auth.two_factor.mode'
     */
    protected function setTwoFactorConfig(array $overrides): void
    {
        $config = container()->get(ConfigurationInterface::class);
        if (!$config instanceof Configuration) {
            return;
        }

        $property = new ReflectionProperty(Configuration::class, 'flatData');
        $flat = $property->getValue($config);

        if (!$this->twoFactorConfigCaptured) {
            $this->originalTwoFactorConfig = $flat;
            $this->twoFactorConfigCaptured = true;
        }

        foreach ($overrides as $key => $value) {
            $flat[$key] = $value;
        }

        $property->setValue($config, $flat);
    }

    protected function restoreTwoFactorConfig(): void
    {
        if (!$this->twoFactorConfigCaptured) {
            return;
        }

        $config = container()->get(ConfigurationInterface::class);
        if ($config instanceof Configuration) {
            new ReflectionProperty(Configuration::class, 'flatData')
                ->setValue($config, $this->originalTwoFactorConfig);
        }

        $this->twoFactorConfigCaptured = false;
        $this->originalTwoFactorConfig = [];
    }
}
