<?php

namespace Tests\Feature\Modules;

use Tests\TestCase;
use App\Modules\PersianModule;
use App\Services\Core\ModuleManager;
use App\Services\Core\EventBus;
use App\Services\Core\ConfigurationManager;
use App\DTOs\TelegramUpdateDTO;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Mockery;

class PersianModuleTest extends TestCase
{
    use RefreshDatabase;

    private PersianModule $module;
    private $mockModuleManager;
    private $mockEventBus;
    private $mockConfigManager;

    protected function setUp(): void
    {
        parent::setUp();
        
        $this->mockModuleManager = Mockery::mock(ModuleManager::class);
        $this->mockEventBus = Mockery::mock(EventBus::class);
        $this->mockConfigManager = Mockery::mock(ConfigurationManager::class);
        
        $this->module = new PersianModule(
            $this->mockModuleManager,
            $this->mockEventBus,
            $this->mockConfigManager
        );
    }

    protected function tearDown(): void
    {
        Mockery::close();
        parent::tearDown();
    }

    public function test_module_registration()
    {
        $this->assertEquals('PersianModule', $this->module->getName());
        $this->assertEquals('1.0.0', $this->module->getVersion());
        $this->assertNotEmpty($this->module->getDescription());
        $this->assertIsArray($this->module->getHandledCommands());
        $this->assertIsArray($this->module->getDependencies());
    }

    public function test_handles_language_command()
    {
        $updateData = [
            'message' => [
                'text' => '/language',
                'chat' => ['id' => 12345],
                'from' => ['id' => 67890, 'first_name' => 'Test']
            ]
        ];

        $update = TelegramUpdateDTO::fromArray($updateData);

        $this->mockEventBus->shouldReceive('dispatch')
            ->with('telegram.send_message', Mockery::any())
            ->once();

        $result = $this->module->handleUpdate($update);
        $this->assertTrue($result);
    }

    public function test_handles_persian_callback()
    {
        $updateData = [
            'callback_query' => [
                'data' => 'lang_fa',
                'message' => [
                    'chat' => ['id' => 12345],
                    'message_id' => 123
                ],
                'from' => ['id' => 67890, 'first_name' => 'Test']
            ]
        ];

        $update = TelegramUpdateDTO::fromArray($updateData);

        $this->mockConfigManager->shouldReceive('set')
            ->with('user.67890.language', 'fa')
            ->once();

        $this->mockEventBus->shouldReceive('dispatch')
            ->with('telegram.edit_message', Mockery::any())
            ->once();

        $this->mockEventBus->shouldReceive('dispatch')
            ->with('user.language_changed', Mockery::any())
            ->once();

        $result = $this->module->handleCallback($update);
        $this->assertTrue($result);
    }

    public function test_handles_english_callback()
    {
        $updateData = [
            'callback_query' => [
                'data' => 'lang_en',
                'message' => [
                    'chat' => ['id' => 12345],
                    'message_id' => 123
                ],
                'from' => ['id' => 67890, 'first_name' => 'Test']
            ]
        ];

        $update = TelegramUpdateDTO::fromArray($updateData);

        $this->mockConfigManager->shouldReceive('set')
            ->with('user.67890.language', 'en')
            ->once();

        $this->mockEventBus->shouldReceive('dispatch')
            ->with('telegram.edit_message', Mockery::any())
            ->once();

        $this->mockEventBus->shouldReceive('dispatch')
            ->with('user.language_changed', Mockery::any())
            ->once();

        $result = $this->module->handleCallback($update);
        $this->assertTrue($result);
    }

    public function test_provides_localization_service()
    {
        $this->mockConfigManager->shouldReceive('get')
            ->with('user.67890.language', 'fa')
            ->andReturn('fa');

        $text = $this->module->translate('welcome_message', 67890);
        $this->assertIsString($text);
        $this->assertNotEmpty($text);
    }

    public function test_format_persian_numbers()
    {
        $englishNumber = '123456';
        $persianNumber = $this->module->formatPersianNumber($englishNumber);
        
        $this->assertNotEquals($englishNumber, $persianNumber);
        $this->assertStringContains('۱', $persianNumber); // Persian digit 1
    }

    public function test_format_persian_date()
    {
        $date = '2023-12-25';
        $persianDate = $this->module->formatPersianDate($date);
        
        $this->assertIsString($persianDate);
        $this->assertNotEmpty($persianDate);
    }

    public function test_module_initialization()
    {
        $this->mockEventBus->shouldReceive('listen')
            ->with('user.created', Mockery::any())
            ->once();

        $this->mockEventBus->shouldReceive('listen')
            ->with('message.pre_send', Mockery::any())
            ->once();

        $result = $this->module->initialize();
        $this->assertTrue($result);
    }

    public function test_module_shutdown()
    {
        $this->mockEventBus->shouldReceive('removeListener')
            ->twice();

        $result = $this->module->shutdown();
        $this->assertTrue($result);
    }

    public function test_get_status()
    {
        $status = $this->module->getStatus();
        
        $this->assertIsArray($status);
        $this->assertArrayHasKey('name', $status);
        $this->assertArrayHasKey('version', $status);
        $this->assertArrayHasKey('enabled', $status);
        $this->assertEquals('PersianModule', $status['name']);
    }

    public function test_handles_unsupported_callback()
    {
        $updateData = [
            'callback_query' => [
                'data' => 'unsupported_callback',
                'message' => [
                    'chat' => ['id' => 12345],
                    'message_id' => 123
                ],
                'from' => ['id' => 67890, 'first_name' => 'Test']
            ]
        ];

        $update = TelegramUpdateDTO::fromArray($updateData);

        $result = $this->module->handleCallback($update);
        $this->assertFalse($result);
    }

    public function test_language_persistence()
    {
        $userId = 67890;
        
        // Mock setting language to Persian
        $this->mockConfigManager->shouldReceive('set')
            ->with("user.{$userId}.language", 'fa')
            ->once();

        $this->mockConfigManager->shouldReceive('get')
            ->with("user.{$userId}.language", 'fa')
            ->andReturn('fa');

        $this->module->setUserLanguage($userId, 'fa');
        $language = $this->module->getUserLanguage($userId);
        
        $this->assertEquals('fa', $language);
    }
}