<?php

namespace Tests\Feature;

use App\Models\Document;
use App\Models\User;
use App\Services\SecurityLogger;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Log;
use Tests\TestCase;

class SecurityLoggerTest extends TestCase
{
    use RefreshDatabase;

    /**
     * 测试记录未授权访问尝试
     * 需求：7.3
     */
    public function test_logs_unauthorized_access_attempt(): void
    {
        // 创建测试数据
        $user = User::factory()->create();
        $document = Document::factory()->create();

        // 模拟日志记录
        Log::shouldReceive('channel')
            ->with('security')
            ->once()
            ->andReturnSelf();

        Log::shouldReceive('warning')
            ->once()
            ->with('未授权访问尝试', \Mockery::on(function ($context) use ($user, $document) {
                return $context['event'] === 'unauthorized_access'
                    && $context['action'] === 'view'
                    && $context['user_id'] === $user->id
                    && $context['document_id'] === $document->id;
            }));

        // 执行测试
        $securityLogger = new SecurityLogger();
        $securityLogger->logUnauthorizedAccess($user, $document, 'view');
    }

    /**
     * 测试 DocumentPolicy 在权限验证失败时记录日志
     * 需求：7.3
     */
    public function test_document_policy_logs_unauthorized_view_attempt(): void
    {
        // 创建测试数据
        $user = User::factory()->create();
        $document = Document::factory()->create();

        // 模拟日志记录
        Log::shouldReceive('channel')
            ->with('security')
            ->once()
            ->andReturnSelf();

        Log::shouldReceive('warning')
            ->once()
            ->with('未授权访问尝试', \Mockery::on(function ($context) {
                return $context['event'] === 'unauthorized_access'
                    && $context['action'] === 'view';
            }));

        // 尝试查看文档（应该失败并记录日志）
        $canView = $user->can('view', $document);

        $this->assertFalse($canView);
    }

    /**
     * 测试 DocumentPolicy 在更新权限验证失败时记录日志
     * 需求：7.3
     */
    public function test_document_policy_logs_unauthorized_update_attempt(): void
    {
        // 创建测试数据
        $uploader = User::factory()->create();
        $otherUser = User::factory()->create();
        $document = Document::factory()->create([
            'uploaded_by' => $uploader->id,
        ]);

        // 模拟日志记录
        Log::shouldReceive('channel')
            ->with('security')
            ->once()
            ->andReturnSelf();

        Log::shouldReceive('warning')
            ->once()
            ->with('未授权访问尝试', \Mockery::on(function ($context) {
                return $context['event'] === 'unauthorized_access'
                    && $context['action'] === 'update';
            }));

        // 尝试更新文档（应该失败并记录日志）
        $canUpdate = $otherUser->can('update', $document);

        $this->assertFalse($canUpdate);
    }

    /**
     * 测试 DocumentPolicy 在删除权限验证失败时记录日志
     * 需求：7.3
     */
    public function test_document_policy_logs_unauthorized_delete_attempt(): void
    {
        // 创建测试数据
        $uploader = User::factory()->create();
        $otherUser = User::factory()->create();
        $document = Document::factory()->create([
            'uploaded_by' => $uploader->id,
        ]);

        // 模拟日志记录
        Log::shouldReceive('channel')
            ->with('security')
            ->once()
            ->andReturnSelf();

        Log::shouldReceive('warning')
            ->once()
            ->with('未授权访问尝试', \Mockery::on(function ($context) {
                return $context['event'] === 'unauthorized_access'
                    && $context['action'] === 'delete';
            }));

        // 尝试删除文档（应该失败并记录日志）
        $canDelete = $otherUser->can('delete', $document);

        $this->assertFalse($canDelete);
    }

    /**
     * 测试安全日志包含完整的上下文信息
     * 需求：7.3
     */
    public function test_security_log_contains_complete_context(): void
    {
        // 创建测试数据
        $user = User::factory()->create([
            'name' => '测试用户',
            'email' => 'test@example.com',
        ]);
        $document = Document::factory()->create([
            'title' => '测试文档',
        ]);

        // 模拟日志记录并验证上下文
        Log::shouldReceive('channel')
            ->with('security')
            ->once()
            ->andReturnSelf();

        Log::shouldReceive('warning')
            ->once()
            ->with('未授权访问尝试', \Mockery::on(function ($context) use ($user, $document) {
                return $context['event'] === 'unauthorized_access'
                    && $context['action'] === 'view'
                    && $context['user_id'] === $user->id
                    && $context['user_name'] === '测试用户'
                    && $context['user_email'] === 'test@example.com'
                    && $context['document_id'] === $document->id
                    && $context['document_title'] === '测试文档'
                    && isset($context['document_knowledge_base_id'])
                    && isset($context['ip_address'])
                    && isset($context['timestamp'])
                    && isset($context['user_agent']);
            }));

        // 执行测试
        $securityLogger = new SecurityLogger();
        $securityLogger->logUnauthorizedAccess($user, $document, 'view');
    }
}
