<?php
declare(strict_types=1);

namespace FreshCloud\Mail\ImapCommands\Tests;

use PHPUnit\Framework\TestCase;
use FreshCloud\Mail\ImapCommands\{
    FolderInfo,
    MessageInfo,
    QuotaInfo,
    InMemoryImapCommands,
};
use FreshCloud\Mail\Log\Logger;
use FreshCloud\Mail\PocketBaseAdapter\PocketBaseAdapter;

final class InMemoryImapCommandsTest extends TestCase
{
    private InMemoryImapCommands $imap;
    private Logger $logger;
    private PocketBaseAdapter $pb;

    protected function setUp(): void
    {
        $this->pb = $this->createMock(PocketBaseAdapter::class);
        $this->logger = $this->createMock(Logger::class);
        $this->imap = new InMemoryImapCommands($this->pb, $this->logger);
    }

    public function testListFoldersReturnsStandardSet(): void
    {
        $folders = $this->imap->listFolders('user1', 'acc1');
        
        $this->assertCount(6, $folders);
        $this->assertContainsOnlyInstancesOf(FolderInfo::class, $folders);
        $this->assertEquals('INBOX', $folders[0]->name);
        $this->assertEquals('Drafts', $folders[1]->name);
    }

    public function testSelectFolderReturnsState(): void
    {
        $state = $this->imap->selectFolder('user1', 'acc1', 'INBOX');
        
        $this->assertIsArray($state);
        $this->assertArrayHasKey('exists', $state);
        $this->assertArrayHasKey('uidvalidity', $state);
        $this->assertEquals(150, $state['exists']);
        $this->assertEquals(123456789, $state['uidvalidity']);
    }

    public function testListMessagesReturnsArray(): void
    {
        $messages = $this->imap->listMessages('user1', 'acc1', 'INBOX');
        
        $this->assertIsArray($messages);
        $this->assertContainsOnlyInstancesOf(MessageInfo::class, $messages);
        $this->assertCount(50, $messages);
        $this->assertEquals(1, $messages[0]->uid);
    }

    public function testListMessagesWithLimit(): void
    {
        $messages = $this->imap->listMessages('user1', 'acc1', 'INBOX', 10);
        
        $this->assertCount(10, $messages);
        $this->assertEquals(1, $messages[0]->uid);
    }

    public function testListMessagesWithOffset(): void
    {
        $messages = $this->imap->listMessages('user1', 'acc1', 'INBOX', 10, 5);
        
        $this->assertCount(10, $messages);
        $this->assertEquals(6, $messages[0]->uid);
    }

    public function testGetQuotaReturnsInfo(): void
    {
        $quota = $this->imap->getQuota('user1', 'acc1');
        
        $this->assertInstanceOf(QuotaInfo::class, $quota);
        $this->assertEquals(524288000, $quota->usedBytes);
        $this->assertEquals(2147483648, $quota->totalBytes);
        $this->assertEquals(24.41, $quota->usagePercent);
    }

    public function testSearchMessagesByFrom(): void
    {
        $messages = $this->imap->searchMessages('user1', 'acc1', 'INBOX', 'user2@example.com');
        
        $this->assertIsArray($messages);
        $this->assertContainsOnlyInstancesOf(MessageInfo::class, $messages);
        $this->assertTrue(count($messages) > 0);
        $this->assertStringContainsString('user2@example.com', $messages[0]->fromAddress);
    }

    public function testSearchMessagesBySubject(): void
    {
        $messages = $this->imap->searchMessages('user1', 'acc1', 'INBOX', 'Message #10');
        
        $this->assertIsArray($messages);
        $this->assertContainsOnlyInstancesOf(MessageInfo::class, $messages);
        $this->assertTrue(count($messages) > 0);
        $this->assertStringContainsString('Message #10', $messages[0]->subject);
    }

    public function testEmptyAccountReturnsEmptyArrays(): void
    {
        $folders = $this->imap->listFolders('empty_user', 'empty_acc');
        $messages = $this->imap->listMessages('empty_user', 'empty_acc', 'INBOX');
        $quota = $this->imap->getQuota('empty_user', 'empty_acc');
        
        $this->assertIsArray($folders);
        $this->assertIsArray($messages);
        $this->assertInstanceOf(QuotaInfo::class, $quota);
        $this->assertCount(6, $folders); // Still returns default folders
        $this->assertCount(50, $messages); // Still returns mock messages
    }
}