<?php

/**
 * 文件功能：扫描并补算用户成就的 Artisan 命令。
 *
 * 支持单用户、全量与最近活跃用户三种扫描方式，便于定时任务和后台补算复用。
 */

namespace App\Console\Commands;

use App\Models\User;
use App\Services\AchievementService;
use Illuminate\Console\Command;

/**
 * 类功能：通过命令行批量检查用户成就进度并写入解锁记录。
 */
class ScanAchievementsCommand extends Command
{
    /**
     * 命令签名。
     *
     * @var string
     */
    protected $signature = 'achievements:scan
                            {--user= : 指定用户 ID 或用户名}
                            {--all : 扫描全部用户}
                            {--notify : 解锁时向用户推送本人可见通知}
                            {--dry-run : 仅预览，不写入成就记录}';

    /**
     * 命令描述。
     *
     * @var string
     */
    protected $description = '扫描聊天室用户成就进度并补齐解锁记录';

    /**
     * 创建命令依赖。
     */
    public function __construct(
        private readonly AchievementService $achievementService,
    ) {
        parent::__construct();
    }

    /**
     * 执行成就扫描命令。
     */
    public function handle(): int
    {
        $notify = (bool) $this->option('notify');
        $dryRun = (bool) $this->option('dry-run');

        if ($this->option('user')) {
            $user = $this->resolveUser((string) $this->option('user'));
            if (! $user) {
                $this->error('未找到指定用户。');

                return self::FAILURE;
            }

            $result = $this->achievementService->scanUser($user, $notify, $dryRun);
            $this->info("已扫描用户 {$user->username}：检查 {$result['checked']} 项，解锁 {$result['unlocked']} 项，更新 {$result['updated']} 项。");

            return self::SUCCESS;
        }

        $query = User::query()->orderBy('id');
        if (! $this->option('all')) {
            // 默认只扫最近活跃用户，避免定时任务每次全表扫描。
            $query->where('updated_at', '>=', now()->subDay())->limit(200);
        }

        $summary = ['users' => 0, 'checked' => 0, 'unlocked' => 0, 'updated' => 0, 'dry_run' => $dryRun];
        $query->chunkById(100, function ($users) use (&$summary, $notify, $dryRun): void {
            $chunkSummary = $this->achievementService->scanUsers($users, $notify, $dryRun);
            $summary['users'] += $chunkSummary['users'];
            $summary['checked'] += $chunkSummary['checked'];
            $summary['unlocked'] += $chunkSummary['unlocked'];
            $summary['updated'] += $chunkSummary['updated'];
        });

        $this->info("成就扫描完成：用户 {$summary['users']} 人，检查 {$summary['checked']} 项，解锁 {$summary['unlocked']} 项，更新 {$summary['updated']} 项。");

        return self::SUCCESS;
    }

    /**
     * 根据 ID 或用户名解析用户。
     */
    private function resolveUser(string $value): ?User
    {
        return User::query()
            ->when(is_numeric($value), fn ($query) => $query->where('id', (int) $value), fn ($query) => $query->where('username', $value))
            ->first();
    }
}
