<?php

namespace MintyPHP\Tests\Unit\Module;

use MintyPHP\App\Module\ModuleRegistry;
use MintyPHP\Module\AddressBook\Providers\AddressBookSearchProvider;
use MintyPHP\Support\SearchConfig;
use MintyPHP\Tests\Support\AppContainerIsolationTrait;
use PHPUnit\Framework\TestCase;

/**
 * Verifies that module search providers are correctly integrated into SearchConfig.
 */
final class SearchProviderCollectionTest extends TestCase
{
    use AppContainerIsolationTrait;

    protected function setUp(): void
    {
        if (!($GLOBALS['minty_app_container'] ?? null) instanceof \MintyPHP\App\AppContainer
            || !($GLOBALS['minty_app_container'])->has(ModuleRegistry::class)) {
            // Restore the bootstrap container that has the module registry
            $container = require dirname(__DIR__, 3) . '/core/App/registerContainer.php';
            $this->pushAppContainer($container);
            setAppContainer($container);
        }
        SearchConfig::resetModuleProviders();
    }

    protected function tearDown(): void
    {
        $this->restoreAppContainer();
        SearchConfig::resetModuleProviders();
    }

    public function testAddressBookModuleIsActiveInRegistry(): void
    {
        /** @var ModuleRegistry $registry */
        $registry = app(ModuleRegistry::class);
        self::assertTrue($registry->hasModule('addressbook'));
        self::assertNotEmpty($registry->getSearchResources());
    }

    public function testCoreResourcesDoNotContainAddressBook(): void
    {
        $coreResources = SearchConfig::resources('test', 'en');
        $coreKeys = array_column($coreResources, 'key');

        self::assertNotContains(
            'address-book',
            $coreKeys,
            'address-book must not be in Core search resources (moved to module)'
        );
    }

    public function testAddressBookSearchProviderDirectly(): void
    {
        $provider = new AddressBookSearchProvider();
        $resources = $provider->resources();

        self::assertArrayHasKey('address-book', $resources);

        $resource = $resources['address-book'];
        self::assertSame('address_book.view', $resource['permission']);
        self::assertStringContainsString('select count', $resource['count_sql']);
        self::assertStringContainsString('select uuid', $resource['preview_sql']);
        self::assertStringContainsString('select uuid', $resource['result_sql']);
        self::assertArrayHasKey('tenant_filter', $resource);
    }

    public function testAddressBookSearchProviderMapResultItem(): void
    {
        $provider = new AddressBookSearchProvider();

        $result = $provider->mapResultItem('address-book', [
            'uuid' => 'abc-123',
            'first_name' => 'Max',
            'last_name' => 'Mustermann',
            'email' => 'max@example.com',
        ]);

        self::assertNotNull($result);
        self::assertSame('Max Mustermann', $result['title']);
        self::assertSame('max@example.com', $result['subtitle']);
        self::assertStringContainsString('address-book/view/abc-123', $result['url']);
        self::assertSame('bi-people', $result['icon']);
    }

    public function testAddressBookSearchProviderListUrl(): void
    {
        $provider = new AddressBookSearchProvider();

        $url = $provider->listUrl('address-book', 'test%20query');

        self::assertStringContainsString('address-book', $url);
        self::assertStringContainsString('search=test%20query', $url);
    }

    public function testAddressBookSearchProviderIgnoresUnknownKey(): void
    {
        $provider = new AddressBookSearchProvider();

        self::assertNull($provider->mapResultItem('unknown', []));
        self::assertSame('', $provider->listUrl('unknown', 'test'));
    }

    public function testModuleResourcesMergedIntoSearchConfig(): void
    {
        $moduleResources = SearchConfig::moduleResources();

        self::assertArrayHasKey(
            'address-book',
            $moduleResources,
            'address-book resource must come from module provider via SearchConfig'
        );
    }

    public function testTenantFilterMergedFromModule(): void
    {
        $filters = SearchConfig::tenantScopeFilters();

        self::assertArrayHasKey(
            'address-book',
            $filters,
            'address-book tenant scope filter must be provided by module'
        );
    }

    public function testSearchConfigListUrlDelegatesToModule(): void
    {
        $url = SearchConfig::listUrl('address-book', 'test query');

        self::assertStringContainsString('address-book', $url);
        self::assertStringContainsString('search=', $url);
    }
}
