<?php

declare(strict_types=1);

namespace App\Tests\Integration\Admin;

use App\Domain\Auth\Role;
use App\Domain\Auth\TokenKind;
use App\Tests\Integration\Support\AppTestCase;

/**
 * `/api/v1/admin/config` — Admin-only effective config with secrets
 * masked.
 */
final class ConfigControllerTest extends AppTestCase
{
    public function testRequiresAdmin(): void
    {
        $token = $this->createToken(TokenKind::Admin, Role::Viewer);
        $resp = $this->request('GET', '/api/v1/admin/config', ['Authorization' => 'Bearer ' . $token]);
        self::assertSame(403, $resp->getStatusCode());
    }

    public function testReturnsSectionsAndMasksSecrets(): void
    {
        $token = $this->createToken(TokenKind::Admin, Role::Admin);
        $resp = $this->request('GET', '/api/v1/admin/config', ['Authorization' => 'Bearer ' . $token]);
        self::assertSame(200, $resp->getStatusCode());
        $body = $this->decode($resp);
        self::assertArrayHasKey('sections', $body);
        $sections = $body['sections'];

        // Required sections
        foreach (['app', 'database', 'auth', 'reputation', 'jobs', 'geoip'] as $section) {
            self::assertArrayHasKey($section, $sections, "missing section $section");
        }

        // INTERNAL_JOB_TOKEN / MAXMIND_LICENSE_KEY: empty in tests, so empty string.
        self::assertSame('', $sections['auth']['INTERNAL_JOB_TOKEN']);
        self::assertSame('', $sections['geoip']['MAXMIND_LICENSE_KEY']);

        // Plain values
        self::assertSame('sqlite', $sections['database']['DB_DRIVER']);
        self::assertSame('dbip', $sections['geoip']['GEOIP_PROVIDER']);
    }

    public function testMasksTokensWhenSet(): void
    {
        // Re-build the container with a configured ui_service_token / internal token / maxmind key
        $settings = $this->withSettings([
            'ui_service_token' => 'irdb_svc_ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
            'internal_job_token' => 'super-secret-internal-token-1234',
            'geoip' => [
                'enabled' => true,
                'provider' => 'maxmind',
                'country_db' => '/tmp/c.mmdb',
                'asn_db' => '/tmp/a.mmdb',
                'maxmind_license_key' => 'real-maxmind-key',
                'ipinfo_token' => 'real-ipinfo-token',
                'refresh_interval_days' => 7,
            ],
        ]);

        if (method_exists($this->container, 'set')) {
            /** @var \DI\Container $c */
            $c = $this->container;
            $c->set('settings', $settings);
            $c->set(
                \App\Application\Admin\ConfigController::class,
                new \App\Application\Admin\ConfigController($settings),
            );
            // Rebuild the app so the route picks up the patched controller.
            $this->app = \App\App\AppFactory::build($this->container);
        }

        $token = $this->createToken(TokenKind::Admin, Role::Admin);
        $resp = $this->request('GET', '/api/v1/admin/config', ['Authorization' => 'Bearer ' . $token]);
        $body = $this->decode($resp);
        $sections = $body['sections'];

        self::assertSame('irdb_svc...', $sections['auth']['UI_SERVICE_TOKEN']);
        self::assertSame('***', $sections['auth']['INTERNAL_JOB_TOKEN']);
        self::assertSame('***', $sections['geoip']['MAXMIND_LICENSE_KEY']);
        self::assertSame('***', $sections['geoip']['IPINFO_TOKEN']);
    }

    /**
     * @return array<string, mixed>
     */
    private function withSettings(array $overrides): array
    {
        // Read the live settings via container, layer the overrides on top.
        /** @var array<string, mixed> $settings */
        $settings = $this->container->get('settings');

        return array_replace($settings, $overrides);
    }
}
