<?php

namespace Tests\Unit;

use App\Jobs\IpRiskDetection;
use Illuminate\Support\Facades\Redis;
use Tests\TestCase;

/**
 * IpRiskDetection Job 单元测试
 *
 * 测试 Job handle() 方法的核心逻辑：
 * - 重复 IP 跳过检测
 * - 空参数跳过
 * - Redis Hash 写入/读取/删除
 */
class IpRiskDetectionTest extends TestCase
{
    // ==================== 边界值：空参数 ====================

    /** @test */
    public function test_skips_when_user_id_is_empty()
    {
        $job = new IpRiskDetection(0, '1.2.3.4');
        $job->handle();
        $this->assertTrue(true);
    }

    /** @test */
    public function test_skips_when_ip_is_empty()
    {
        $job = new IpRiskDetection(12345, '');
        $job->handle();
        $this->assertTrue(true);
    }

    /** @test */
    public function test_skips_when_both_are_empty()
    {
        $job = new IpRiskDetection(0, '');
        $job->handle();
        $this->assertTrue(true);
    }

    // ==================== 重复检测跳过 ====================

    /** @test */
    public function test_skips_detection_when_same_ip_in_today_hash()
    {
        $userId = 10001;
        $ip = '73.162.0.1';
        $todayKey = IpRiskDetection::LAST_DETECTED_PREFIX . date('Ymd');

        Redis::shouldReceive('hget')
            ->once()
            ->with($todayKey, $userId)
            ->andReturn($ip);

        $job = new IpRiskDetection($userId, $ip);
        $job->handle();

        $this->assertTrue(true);
    }

    /** @test */
    public function test_skips_detection_when_same_ip_in_yesterday_hash()
    {
        $userId = 10001;
        $ip = '73.162.0.1';
        $todayKey = IpRiskDetection::LAST_DETECTED_PREFIX . date('Ymd');
        $yesterdayKey = IpRiskDetection::LAST_DETECTED_PREFIX . date('Ymd', strtotime('-1 day'));

        // today miss → yesterday hit
        Redis::shouldReceive('hget')
            ->once()
            ->with($todayKey, $userId)
            ->andReturn(null);
        Redis::shouldReceive('hget')
            ->once()
            ->with($yesterdayKey, $userId)
            ->andReturn($ip);

        $job = new IpRiskDetection($userId, $ip);
        $job->handle();

        $this->assertTrue(true);
    }

    // ==================== 容器内集成测试 ====================

    /**
     * 以下测试需要模拟 IpRiskService，但 Job 内部通过 new 创建服务实例。
     *
     * 测试策略：
     * - IpRiskService 自身的 detect() 逻辑已在 IpRiskServiceTest 中覆盖
     * - Job 与 Redis 的交互在上述测试中覆盖
     * - 完整链路测试建议在验收环境中通过实际登录/注册流程验证
     */

    /** @test */
    public function test_has_correct_constants()
    {
        $this->assertEquals('ip_risk_users', IpRiskDetection::REDIS_HASH_KEY);
        $this->assertEquals('ip_risk_last_detected:', IpRiskDetection::LAST_DETECTED_PREFIX);
        $this->assertEquals(3, IpRiskDetection::DETECTION_WINDOW_DAYS);
    }

    /** @test */
    public function test_implements_should_queue()
    {
        $job = new IpRiskDetection(1, '1.2.3.4');
        $this->assertInstanceOf(\Illuminate\Contracts\Queue\ShouldQueue::class, $job);
    }
}
