<?php

namespace Tests\Unit;

use App\Http\logic\admin\SignInRewardLogic;
use App\Models\SignInRewardConfig;
use Tests\TestCase;

/**
 * 签到奖励配置业务逻辑单元测试
 *
 * 测试 SignInRewardLogic 的 CRUD 操作
 */
class SignInRewardLogicTest extends TestCase
{
    /**
     * @var SignInRewardLogic
     */
    protected $logic;

    /**
     * 设置测试环境
     */
    public function setUp(): void
    {
        parent::setUp();
        $this->logic = new SignInRewardLogic();

        // 清理测试数据
        SignInRewardConfig::query()->delete();
    }

    /**
     * 测试创建有效的签到奖励配置
     *
     * @return void
     */
    public function test_create_valid_reward_config()
    {
        $data = [
            'DayNumber' => 1,
            'RewardScore' => 100,
        ];

        $result = $this->logic->create($data);

        $this->assertTrue($result);
        $this->assertDatabaseHas('QPAccountsDB.dbo.SignInRewardConfig', $data);
    }

    /**
     * 测试创建配置时缺少必要字段
     *
     * @return void
     */
    public function test_create_missing_day_number()
    {
        $data = [
            'RewardScore' => 100,
        ];

        $result = $this->logic->create($data);

        $this->assertFalse($result);
        $this->assertStringContainsString('签到天数', $this->logic->getError());
    }

    /**
     * 测试创建配置时奖励积分缺失
     *
     * @return void
     */
    public function test_create_missing_reward_score()
    {
        $data = [
            'DayNumber' => 1,
        ];

        $result = $this->logic->create($data);

        $this->assertFalse($result);
        $this->assertStringContainsString('奖励积分', $this->logic->getError());
    }

    /**
     * 测试创建配置时使用无效的天数（非正整数）
     *
     * @return void
     */
    public function test_create_invalid_day_number()
    {
        $data = [
            'DayNumber' => -1,
            'RewardScore' => 100,
        ];

        $result = $this->logic->create($data);

        $this->assertFalse($result);
        $this->assertStringContainsString('正整数', $this->logic->getError());
    }

    /**
     * 测试创建配置时使用负数的奖励积分
     *
     * @return void
     */
    public function test_create_negative_reward_score()
    {
        $data = [
            'DayNumber' => 1,
            'RewardScore' => -100,
        ];

        $result = $this->logic->create($data);

        $this->assertFalse($result);
        $this->assertStringContainsString('非负整数', $this->logic->getError());
    }

    /**
     * 测试创建重复的天数配置
     *
     * @return void
     */
    public function test_create_duplicate_day_number()
    {
        // 创建第一条记录
        $data1 = [
            'DayNumber' => 1,
            'RewardScore' => 100,
        ];
        $this->logic->create($data1);

        // 尝试创建相同的天数
        $result = $this->logic->create($data1);

        $this->assertFalse($result);
        $this->assertStringContainsString('已存在', $this->logic->getError());
    }

    /**
     * 测试获取列表
     *
     * @return void
     */
    public function test_get_list()
    {
        // 创建多条记录
        for ($i = 1; $i <= 3; $i++) {
            $data = [
                'DayNumber' => $i,
                'RewardScore' => $i * 100,
            ];
            $this->logic->create($data);
        }

        $list = $this->logic->getList(10);

        $this->assertCount(3, $list);
    }

    /**
     * 测试按天数查找奖励配置
     *
     * @return void
     */
    public function test_find_by_day()
    {
        $data = [
            'DayNumber' => 5,
            'RewardScore' => 500,
        ];
        $this->logic->create($data);

        $config = $this->logic->getByDay(5);

        $this->assertNotNull($config);
        $this->assertEquals(5, $config->DayNumber);
        $this->assertEquals(500, $config->RewardScore);
    }

    /**
     * 测试查找不存在的天数
     *
     * @return void
     */
    public function test_find_by_day_not_found()
    {
        $config = $this->logic->getByDay(999);

        $this->assertNull($config);
    }

    /**
     * 测试更新奖励配置
     *
     * @return void
     */
    public function test_update_reward_config()
    {
        // 创建初始记录
        $data = [
            'DayNumber' => 2,
            'RewardScore' => 200,
        ];
        $this->logic->create($data);

        // 更新记录
        $updateData = [
            'RewardScore' => 300,
        ];
        $result = $this->logic->update(2, $updateData);

        $this->assertTrue($result);
        $this->assertDatabaseHas('QPAccountsDB.dbo.SignInRewardConfig', [
            'DayNumber' => 2,
            'RewardScore' => 300,
        ]);
    }

    /**
     * 测试更新时使用无效的奖励积分
     *
     * @return void
     */
    public function test_update_invalid_reward_score()
    {
        // 创建初始记录
        $data = [
            'DayNumber' => 2,
            'RewardScore' => 200,
        ];
        $this->logic->create($data);

        // 尝试使用无效的奖励积分更新
        $updateData = [
            'RewardScore' => 'invalid',
        ];
        $result = $this->logic->update(2, $updateData);

        $this->assertFalse($result);
    }

    /**
     * 测试更新不存在的记录
     *
     * @return void
     */
    public function test_update_nonexistent_record()
    {
        $updateData = [
            'RewardScore' => 300,
        ];

        $this->expectException(\Illuminate\Database\Eloquent\ModelNotFoundException::class);
        $this->logic->update(999, $updateData);
    }

    /**
     * 测试删除奖励配置
     *
     * @return void
     */
    public function test_delete_reward_config()
    {
        // 创建初始记录
        $data = [
            'DayNumber' => 3,
            'RewardScore' => 300,
        ];
        $this->logic->create($data);

        // 删除记录
        $result = $this->logic->delete(3);

        $this->assertTrue($result);
        $this->assertDatabaseMissing('QPAccountsDB.dbo.SignInRewardConfig', [
            'DayNumber' => 3,
        ]);
    }

    /**
     * 测试删除不存在的记录
     *
     * @return void
     */
    public function test_delete_nonexistent_record()
    {
        $this->expectException(\Illuminate\Database\Eloquent\ModelNotFoundException::class);
        $this->logic->delete(999);
    }

    /**
     * 清理测试数据
     */
    public function tearDown(): void
    {
        SignInRewardConfig::query()->delete();
        parent::tearDown();
    }
}
