<?php

namespace Tests\Feature;

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

class ActivityLogTest extends TestCase
{
    use RefreshDatabase;

    protected User $user;

    protected function setUp(): void
    {
        parent::setUp();
        
        // 创建测试用户
        $this->user = User::factory()->create([
            'name' => '测试用户',
            'email' => 'test@example.com',
        ]);
        
        $this->actingAs($this->user);
    }

    /**
     * 测试日志自动记录 - 创建操作
     */
    public function test_activity_log_records_create_operation(): void
    {
        // 创建系统设置
        $setting = SystemSetting::create([
            'key' => 'test.setting',
            'value' => ['test' => 'value'],
            'group' => 'test',
            'description' => '测试设置',
        ]);

        // 验证日志是否记录
        $this->assertDatabaseHas('activity_log', [
            'subject_type' => SystemSetting::class,
            'subject_id' => $setting->id,
            'description' => '系统设置已created',
            'causer_id' => $this->user->id,
        ]);

        // 获取日志记录
        $log = Activity::where('subject_id', $setting->id)
            ->where('subject_type', SystemSetting::class)
            ->where('description', '系统设置已created')
            ->first();

        $this->assertNotNull($log);
        $this->assertEquals($this->user->id, $log->causer_id);
        $this->assertArrayHasKey('attributes', $log->properties->toArray());
    }

    /**
     * 测试日志自动记录 - 更新操作
     */
    public function test_activity_log_records_update_operation(): void
    {
        // 创建系统设置
        $setting = SystemSetting::create([
            'key' => 'test.setting',
            'value' => ['test' => 'value'],
            'group' => 'test',
            'description' => '测试设置',
        ]);

        // 清空之前的日志
        Activity::query()->delete();

        // 更新设置
        $setting->update([
            'value' => ['test' => 'updated_value'],
            'description' => '更新后的测试设置',
        ]);

        // 验证日志是否记录
        $this->assertDatabaseHas('activity_log', [
            'subject_type' => SystemSetting::class,
            'subject_id' => $setting->id,
            'description' => '系统设置已updated',
            'causer_id' => $this->user->id,
        ]);

        // 获取日志记录
        $log = Activity::where('subject_id', $setting->id)
            ->where('subject_type', SystemSetting::class)
            ->where('description', '系统设置已updated')
            ->first();

        $this->assertNotNull($log);
        $this->assertArrayHasKey('attributes', $log->properties->toArray());
        $this->assertArrayHasKey('old', $log->properties->toArray());
        
        // 验证变更内容
        $properties = $log->properties->toArray();
        $this->assertEquals(['test' => 'updated_value'], $properties['attributes']['value']);
        $this->assertEquals(['test' => 'value'], $properties['old']['value']);
    }

    /**
     * 测试日志自动记录 - 删除操作
     */
    public function test_activity_log_records_delete_operation(): void
    {
        // 创建系统设置
        $setting = SystemSetting::create([
            'key' => 'test.setting',
            'value' => ['test' => 'value'],
            'group' => 'test',
            'description' => '测试设置',
        ]);

        $settingId = $setting->id;

        // 清空之前的日志
        Activity::query()->delete();

        // 删除设置
        $setting->delete();

        // 验证日志是否记录
        $this->assertDatabaseHas('activity_log', [
            'subject_type' => SystemSetting::class,
            'subject_id' => $settingId,
            'description' => '系统设置已deleted',
            'causer_id' => $this->user->id,
        ]);

        // 获取日志记录
        $log = Activity::where('subject_id', $settingId)
            ->where('subject_type', SystemSetting::class)
            ->where('description', '系统设置已deleted')
            ->first();

        $this->assertNotNull($log);
        // 删除操作可能只记录旧值，不一定有 attributes
        $this->assertNotEmpty($log->properties->toArray());
    }

    /**
     * 测试日志筛选 - 按时间范围
     */
    public function test_activity_log_filter_by_date_range(): void
    {
        // 创建不同时间的日志
        $yesterday = now()->subDay();
        $today = now();
        
        Activity::create([
            'log_name' => 'default',
            'description' => 'created',
            'subject_type' => SystemSetting::class,
            'subject_id' => 1,
            'causer_type' => User::class,
            'causer_id' => $this->user->id,
            'properties' => ['test' => 'value'],
            'created_at' => $yesterday,
        ]);

        Activity::create([
            'log_name' => 'default',
            'description' => 'updated',
            'subject_type' => SystemSetting::class,
            'subject_id' => 2,
            'causer_type' => User::class,
            'causer_id' => $this->user->id,
            'properties' => ['test' => 'value'],
            'created_at' => $today,
        ]);

        // 测试筛选今天的日志
        $todayLogs = Activity::whereDate('created_at', '>=', $today->format('Y-m-d'))
            ->whereDate('created_at', '<=', $today->format('Y-m-d'))
            ->get();

        $this->assertCount(1, $todayLogs);
        $this->assertEquals('updated', $todayLogs->first()->description);
    }

    /**
     * 测试日志筛选 - 按操作类型
     */
    public function test_activity_log_filter_by_description(): void
    {
        // 创建不同类型的日志
        Activity::create([
            'log_name' => 'default',
            'description' => 'created',
            'subject_type' => SystemSetting::class,
            'subject_id' => 1,
            'causer_type' => User::class,
            'causer_id' => $this->user->id,
            'properties' => ['test' => 'value'],
        ]);

        Activity::create([
            'log_name' => 'default',
            'description' => 'updated',
            'subject_type' => SystemSetting::class,
            'subject_id' => 2,
            'causer_type' => User::class,
            'causer_id' => $this->user->id,
            'properties' => ['test' => 'value'],
        ]);

        Activity::create([
            'log_name' => 'default',
            'description' => 'deleted',
            'subject_type' => SystemSetting::class,
            'subject_id' => 3,
            'causer_type' => User::class,
            'causer_id' => $this->user->id,
            'properties' => ['test' => 'value'],
        ]);

        // 测试筛选创建操作
        $createdLogs = Activity::where('description', 'created')->get();
        $this->assertCount(1, $createdLogs);

        // 测试筛选更新操作
        $updatedLogs = Activity::where('description', 'updated')->get();
        $this->assertCount(1, $updatedLogs);

        // 测试筛选删除操作
        $deletedLogs = Activity::where('description', 'deleted')->get();
        $this->assertCount(1, $deletedLogs);
    }

    /**
     * 测试日志筛选 - 按用户
     */
    public function test_activity_log_filter_by_user(): void
    {
        // 创建另一个用户
        $anotherUser = User::factory()->create([
            'name' => '另一个用户',
            'email' => 'another@example.com',
        ]);

        // 创建不同用户的日志
        Activity::create([
            'log_name' => 'default',
            'description' => 'created',
            'subject_type' => SystemSetting::class,
            'subject_id' => 1,
            'causer_type' => User::class,
            'causer_id' => $this->user->id,
            'properties' => ['test' => 'value'],
        ]);

        Activity::create([
            'log_name' => 'default',
            'description' => 'updated',
            'subject_type' => SystemSetting::class,
            'subject_id' => 2,
            'causer_type' => User::class,
            'causer_id' => $anotherUser->id,
            'properties' => ['test' => 'value'],
        ]);

        // 测试筛选当前用户的日志
        $userLogs = Activity::where('causer_id', $this->user->id)->get();
        $this->assertCount(1, $userLogs);

        // 测试筛选另一个用户的日志
        $anotherUserLogs = Activity::where('causer_id', $anotherUser->id)->get();
        $this->assertCount(1, $anotherUserLogs);
    }

    /**
     * 测试日志筛选 - 按对象类型
     */
    public function test_activity_log_filter_by_subject_type(): void
    {
        // 创建不同对象类型的日志
        Activity::create([
            'log_name' => 'default',
            'description' => 'created',
            'subject_type' => SystemSetting::class,
            'subject_id' => 1,
            'causer_type' => User::class,
            'causer_id' => $this->user->id,
            'properties' => ['test' => 'value'],
        ]);

        Activity::create([
            'log_name' => 'default',
            'description' => 'updated',
            'subject_type' => User::class,
            'subject_id' => 2,
            'causer_type' => User::class,
            'causer_id' => $this->user->id,
            'properties' => ['test' => 'value'],
        ]);

        // 测试筛选 SystemSetting 类型
        $settingLogs = Activity::where('subject_type', SystemSetting::class)->get();
        $this->assertCount(1, $settingLogs);

        // 测试筛选 User 类型
        $userLogs = Activity::where('subject_type', User::class)->get();
        $this->assertCount(1, $userLogs);
    }

    /**
     * 测试日志详情查看
     */
    public function test_activity_log_view_details(): void
    {
        // 创建带有详细变更的日志
        $log = Activity::create([
            'log_name' => 'default',
            'description' => 'updated',
            'subject_type' => SystemSetting::class,
            'subject_id' => 1,
            'causer_type' => User::class,
            'causer_id' => $this->user->id,
            'properties' => [
                'attributes' => [
                    'key' => 'test.setting',
                    'value' => ['new' => 'value'],
                    'description' => '新描述',
                ],
                'old' => [
                    'key' => 'test.setting',
                    'value' => ['old' => 'value'],
                    'description' => '旧描述',
                ],
            ],
        ]);

        // 验证日志属性
        $this->assertNotNull($log->properties);
        $this->assertIsArray($log->properties->toArray());
        $this->assertArrayHasKey('attributes', $log->properties->toArray());
        $this->assertArrayHasKey('old', $log->properties->toArray());

        // 验证变更内容
        $properties = $log->properties->toArray();
        $this->assertEquals(['new' => 'value'], $properties['attributes']['value']);
        $this->assertEquals(['old' => 'value'], $properties['old']['value']);
        $this->assertEquals('新描述', $properties['attributes']['description']);
        $this->assertEquals('旧描述', $properties['old']['description']);
    }
}
