<?php

namespace Tests\Feature;

use App\Models\SystemSetting;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class SystemSettingValidationTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();
        
        // 创建测试用户
        $this->actingAs(User::factory()->create());
    }

    /** @test */
    public function it_validates_required_fields()
    {
        // 测试 key 字段必填 - 数据库层面会抛出异常
        $this->expectException(\Illuminate\Database\QueryException::class);
        
        SystemSetting::create([
            'value' => ['test' => 'value'],
            'group' => 'system',
        ]);
    }

    /** @test */
    public function it_validates_key_uniqueness()
    {
        // 创建第一个配置
        SystemSetting::create([
            'key' => 'test.unique',
            'value' => ['unique' => 'value1'],
            'group' => 'system',
            'description' => '测试唯一性',
        ]);

        // 尝试创建重复的 key
        $this->expectException(\Illuminate\Database\QueryException::class);
        
        SystemSetting::create([
            'key' => 'test.unique',
            'value' => ['unique' => 'value2'],
            'group' => 'system',
            'description' => '测试唯一性2',
        ]);
    }

    /** @test */
    public function it_validates_numeric_ranges_for_embedding_dimensions()
    {
        // 测试嵌入维度的数值范围
        $validDimensions = [128, 256, 512, 1024, 1536, 3072];
        
        foreach ($validDimensions as $dimension) {
            $setting = SystemSetting::updateOrCreate(
                ['key' => 'embedding.dimensions'],
                [
                    'value' => ['dimensions' => $dimension],
                    'group' => 'embedding',
                    'description' => '向量维度',
                ]
            );
            
            $this->assertEquals($dimension, $setting->value['dimensions']);
        }
    }

    /** @test */
    public function it_validates_numeric_ranges_for_chunking_parameters()
    {
        // 测试分块参数的数值范围
        $chunkSettings = [
            'chunking.chunk_size' => ['chunk_size' => 1000],
            'chunking.chunk_overlap' => ['chunk_overlap' => 200],
            'chunking.min_chunk_size' => ['min_chunk_size' => 100],
        ];

        foreach ($chunkSettings as $key => $value) {
            $setting = SystemSetting::updateOrCreate(
                ['key' => $key],
                [
                    'value' => $value,
                    'group' => 'chunking',
                    'description' => '分块参数',
                ]
            );
            
            $this->assertIsNumeric(reset($value));
        }
    }

    /** @test */
    public function it_validates_url_format_for_endpoint()
    {
        // 测试 URL 格式验证
        $validUrls = [
            'https://api.openai.com/v1/embeddings',
            'https://example.com/api/embed',
        ];

        foreach ($validUrls as $url) {
            $setting = SystemSetting::updateOrCreate(
                ['key' => 'embedding.endpoint_url'],
                [
                    'value' => ['endpoint_url' => $url],
                    'group' => 'embedding',
                    'description' => 'API端点',
                ]
            );
            
            $this->assertTrue(filter_var($url, FILTER_VALIDATE_URL) !== false);
        }
    }

    /** @test */
    public function it_validates_system_timeout_range()
    {
        // 测试超时时间范围（10-300秒）
        $validTimeouts = [10, 60, 120, 300];
        
        foreach ($validTimeouts as $timeout) {
            $setting = SystemSetting::updateOrCreate(
                ['key' => 'system.timeout'],
                [
                    'value' => ['timeout' => $timeout],
                    'group' => 'system',
                    'description' => '超时时间',
                ]
            );
            
            $this->assertGreaterThanOrEqual(10, $timeout);
            $this->assertLessThanOrEqual(300, $timeout);
        }
    }

    /** @test */
    public function it_validates_search_similarity_threshold_range()
    {
        // 测试相似度阈值范围（0-1）
        $validThresholds = [0.0, 0.5, 0.7, 0.9, 1.0];
        
        foreach ($validThresholds as $threshold) {
            $setting = SystemSetting::updateOrCreate(
                ['key' => 'search.similarity_threshold'],
                [
                    'value' => ['similarity_threshold' => $threshold],
                    'group' => 'search',
                    'description' => '相似度阈值',
                ]
            );
            
            $this->assertGreaterThanOrEqual(0, $threshold);
            $this->assertLessThanOrEqual(1, $threshold);
        }
    }

    /** @test */
    public function it_validates_array_type_for_allowed_file_types()
    {
        // 测试文件类型数组
        $fileTypes = ['pdf', 'docx', 'txt', 'md'];
        
        $setting = SystemSetting::updateOrCreate(
            ['key' => 'system.allowed_file_types'],
            [
                'value' => ['allowed_file_types' => $fileTypes],
                'group' => 'system',
                'description' => '允许的文件类型',
            ]
        );
        
        $this->assertIsArray($setting->value['allowed_file_types']);
        $this->assertCount(4, $setting->value['allowed_file_types']);
    }

    /** @test */
    public function it_validates_boolean_type_for_toggles()
    {
        // 测试布尔类型字段
        $booleanSettings = [
            'is_public' => true,
            'search.enable_rerank' => false,
        ];

        foreach ($booleanSettings as $key => $value) {
            if ($key === 'is_public') {
                $setting = SystemSetting::create([
                    'key' => 'test.public',
                    'value' => ['public' => 'test'],
                    'group' => 'system',
                    'description' => '测试',
                    'is_public' => $value,
                ]);
                
                $this->assertIsBool($setting->is_public);
            } else {
                $setting = SystemSetting::updateOrCreate(
                    ['key' => $key],
                    [
                        'value' => ['enable_rerank' => $value],
                        'group' => 'search',
                        'description' => '启用重排序',
                    ]
                );
                
                $this->assertIsBool($value);
            }
        }
    }

    /** @test */
    public function it_validates_max_length_constraints()
    {
        // 测试最大长度限制
        $setting = SystemSetting::create([
            'key' => 'test.maxlength',
            'value' => ['maxlength' => 'test'],
            'group' => 'system',
            'description' => '测试最大长度',
        ]);

        // key 最大长度 255
        $this->assertLessThanOrEqual(255, strlen($setting->key));
        
        // description 最大长度 65535
        $this->assertLessThanOrEqual(65535, strlen($setting->description ?? ''));
    }
}
