<?php

namespace MintyPHP\Tests\Unit\Module;

use MintyPHP\App\AppContainer;
use MintyPHP\App\Module\Contracts\SessionProvider;
use MintyPHP\Module\AddressBook\Providers\AddressBookSessionProvider;
use PHPUnit\Framework\TestCase;

/**
 * @covers \MintyPHP\Module\AddressBook\Providers\AddressBookSessionProvider
 */
final class SessionProviderTest extends TestCase
{
    protected function setUp(): void
    {
        $_SESSION = [];
    }

    protected function tearDown(): void
    {
        $_SESSION = [];
    }

    /**
     * Create a real AppContainer that returns null for any get() call.
     * AppContainer is final and cannot be mocked.
     */
    private function emptyContainer(): AppContainer
    {
        return new AppContainer();
    }

    public function testImplementsSessionProviderContract(): void
    {
        $provider = new AddressBookSessionProvider();
        self::assertInstanceOf(SessionProvider::class, $provider);
    }

    public function testPopulateWithInvalidUserClearsSessionKey(): void
    {
        $_SESSION['module.addressbook.departments_by_tenant'] = [['tenant' => 'old']];

        $provider = new AddressBookSessionProvider();
        $provider->populate(['id' => 0], $this->emptyContainer());

        self::assertArrayNotHasKey('module.addressbook.departments_by_tenant', $_SESSION);
    }

    public function testPopulateWithMissingUserIdClearsSessionKey(): void
    {
        $_SESSION['module.addressbook.departments_by_tenant'] = [['tenant' => 'old']];

        $provider = new AddressBookSessionProvider();
        $provider->populate([], $this->emptyContainer());

        self::assertArrayNotHasKey('module.addressbook.departments_by_tenant', $_SESSION);
    }

    public function testPopulateReturnsEarlyWhenContainerMissesDependencies(): void
    {
        $provider = new AddressBookSessionProvider();
        // Container has no bindings → get() will throw, but provider guards with instanceof check
        // The provider should handle this gracefully (no session key set)
        try {
            $provider->populate(['id' => 42], $this->emptyContainer());
        } catch (\Throwable) {
            // Provider may throw if container has no binding — that's acceptable;
            // in production, bindings are always registered before providers run.
        }

        self::assertArrayNotHasKey('module.addressbook.departments_by_tenant', $_SESSION);
    }

    public function testClearRemovesSessionKey(): void
    {
        $_SESSION['module.addressbook.departments_by_tenant'] = [
            ['tenant' => ['uuid' => 'abc'], 'departments' => []],
        ];

        $provider = new AddressBookSessionProvider();
        $provider->clear();

        self::assertArrayNotHasKey('module.addressbook.departments_by_tenant', $_SESSION);
    }

    public function testClearIsIdempotent(): void
    {
        // Key doesn't exist — clear() should not throw
        $provider = new AddressBookSessionProvider();
        $provider->clear();

        self::assertArrayNotHasKey('module.addressbook.departments_by_tenant', $_SESSION);
    }
}
