<?php

namespace Tests\Feature;

use App\Jobs\ConvertDocumentToMarkdown;
use App\Models\Document;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\DB;
use Tests\TestCase;

/**
 * Swoole 队列系统集成测试
 * 
 * 验证队列系统在 Swoole 环境下的完整集成功能
 */
class SwooleQueueIntegrationTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();
        
        // 设置测试存储磁盘
        Storage::fake('documents');
        Storage::fake('markdown');
        
        // 禁用搜索功能以避免 Meilisearch 连接问题
        config(['scout.driver' => 'null']);
    }

    /**
     * 测试队列任务的完整生命周期
     * 
     * @test
     */
    public function test_queue_job_complete_lifecycle()
    {
        // 创建测试数据
        $user = User::factory()->create();
        $document = Document::factory()->create([
            'uploaded_by' => $user->id,
            'title' => '集成测试文档',
            'file_path' => 'integration-test.docx',
        ]);

        // 使用模拟队列来避免实际执行
        Queue::fake();

        // 分发队列任务
        Queue::pushOn('default', new ConvertDocumentToMarkdown($document));

        // 验证任务已被分发
        Queue::assertPushed(ConvertDocumentToMarkdown::class);

        // 验证任务可以被正确序列化和反序列化
        $job = new ConvertDocumentToMarkdown($document);
        $serialized = serialize($job);
        $unserialized = unserialize($serialized);
        
        $this->assertInstanceOf(ConvertDocumentToMarkdown::class, $unserialized);
        
        // 使用反射来访问受保护的属性
        $reflection = new \ReflectionClass($unserialized);
        $documentProperty = $reflection->getProperty('document');
        $documentProperty->setAccessible(true);
        $jobDocument = $documentProperty->getValue($unserialized);
        $this->assertEquals($document->id, $jobDocument->id);
    }

    /**
     * 测试队列任务在高并发下的表现
     * 
     * @test
     */
    public function test_queue_performance_under_load()
    {
        // 创建测试用户
        $user = User::factory()->create();
        
        // 创建多个文档
        $documents = Document::factory()->count(10)->create([
            'uploaded_by' => $user->id,
        ]);

        // 使用模拟队列
        Queue::fake();

        $startTime = microtime(true);
        $startMemory = memory_get_usage();

        // 批量分发队列任务
        foreach ($documents as $document) {
            Queue::pushOn('default', new ConvertDocumentToMarkdown($document));
        }

        $endTime = microtime(true);
        $endMemory = memory_get_usage();

        // 验证性能指标
        $executionTime = $endTime - $startTime;
        $memoryUsage = $endMemory - $startMemory;

        $this->assertLessThan(1.0, $executionTime, '队列任务分发时间过长');
        $this->assertLessThan(5 * 1024 * 1024, $memoryUsage, '队列任务内存使用过多');

        // 验证所有任务都已分发
        Queue::assertPushed(ConvertDocumentToMarkdown::class, 10);
    }

    /**
     * 测试队列任务的错误恢复机制
     * 
     * @test
     */
    public function test_queue_error_recovery()
    {
        // 创建测试文档
        $user = User::factory()->create();
        $document = Document::factory()->create([
            'uploaded_by' => $user->id,
            'title' => '错误恢复测试',
        ]);

        // 创建一个会失败的任务
        $job = new ConvertDocumentToMarkdown($document);
        
        // 模拟任务失败
        try {
            $job->failed(new \Exception('模拟任务失败'));
        } catch (\Exception $e) {
            // 预期的异常
        }

        // 验证失败处理机制工作正常
        $this->assertTrue(true, '错误恢复机制测试完成');
    }

    /**
     * 测试队列任务的内存清理
     * 
     * @test
     */
    public function test_queue_memory_cleanup()
    {
        $initialMemory = memory_get_usage();

        // 创建和处理多个任务
        $user = User::factory()->create();
        
        for ($i = 0; $i < 5; $i++) {
            $document = Document::factory()->create(['uploaded_by' => $user->id]);
            $job = new ConvertDocumentToMarkdown($document);
            
            // 模拟任务处理
            unset($job);
            unset($document);
        }

        // 强制垃圾回收
        gc_collect_cycles();

        $finalMemory = memory_get_usage();
        $memoryIncrease = $finalMemory - $initialMemory;

        // 验证内存没有显著增长
        $this->assertLessThan(2 * 1024 * 1024, $memoryIncrease, '队列任务存在内存泄漏');
    }

    /**
     * 测试队列配置的动态加载
     * 
     * @test
     */
    public function test_queue_configuration_loading()
    {
        // 验证队列配置可以正确加载
        $queueConfig = config('queue');
        $this->assertIsArray($queueConfig, '队列配置加载失败');

        // 验证默认连接配置
        $defaultConnection = $queueConfig['default'];
        $this->assertNotEmpty($defaultConnection, '默认队列连接未配置');

        // 验证连接配置存在
        $connectionConfig = $queueConfig['connections'][$defaultConnection] ?? null;
        $this->assertNotNull($connectionConfig, '队列连接配置不存在');
        $this->assertArrayHasKey('driver', $connectionConfig, '队列驱动未配置');
    }

    /**
     * 测试队列任务的优先级处理
     * 
     * @test
     */
    public function test_queue_priority_handling()
    {
        // 创建测试数据
        $user = User::factory()->create();
        $highPriorityDoc = Document::factory()->create([
            'uploaded_by' => $user->id,
            'title' => '高优先级文档',
        ]);
        $lowPriorityDoc = Document::factory()->create([
            'uploaded_by' => $user->id,
            'title' => '低优先级文档',
        ]);

        // 使用模拟队列
        Queue::fake();

        // 分发不同优先级的任务
        $highPriorityJob = (new ConvertDocumentToMarkdown($highPriorityDoc))->onQueue('high');
        $lowPriorityJob = (new ConvertDocumentToMarkdown($lowPriorityDoc))->onQueue('default');

        Queue::push($lowPriorityJob);
        Queue::push($highPriorityJob);

        // 验证任务已正确分发
        Queue::assertPushed(ConvertDocumentToMarkdown::class, 2);
    }

    /**
     * 测试队列任务的批处理功能
     * 
     * @test
     */
    public function test_queue_batch_processing()
    {
        // 创建测试数据
        $user = User::factory()->create();
        $documents = Document::factory()->count(3)->create(['uploaded_by' => $user->id]);

        // 使用模拟队列
        Queue::fake();

        // 创建批处理任务
        $jobs = $documents->map(function ($document) {
            return new ConvertDocumentToMarkdown($document);
        });

        // 批量分发任务
        foreach ($jobs as $job) {
            Queue::push($job);
        }

        // 验证批处理功能
        Queue::assertPushed(ConvertDocumentToMarkdown::class, 3);
    }

    /**
     * 测试队列任务的超时处理
     * 
     * @test
     */
    public function test_queue_timeout_handling()
    {
        // 创建测试文档
        $user = User::factory()->create();
        $document = Document::factory()->create(['uploaded_by' => $user->id]);

        // 创建任务并检查超时配置
        $job = new ConvertDocumentToMarkdown($document);
        
        $this->assertIsNumeric($job->timeout, '任务超时配置无效');
        $this->assertGreaterThan(0, $job->timeout, '任务超时时间必须大于 0');
        
        // 验证超时时间合理
        $this->assertLessThanOrEqual(600, $job->timeout, '任务超时时间过长');
    }
}