<?php

/**
 * 文件功能：自动关闭掉线职务日志指令
 *
 * 每 15 分钟由 Laravel Scheduler 调用，扫描 position_duty_logs 表中：
 * - logout_at IS NULL（尚未结算的开放日志）
 * - updated_at 超过 15 分钟未刷新（说明心跳已中断，用户已掉线/关闭浏览器）
 *
 * 对此类日志写入 logout_at = NOW()，保留 duration_seconds 现有值不清零，
 * 确保累计时长计算准确，不因掉线而永久悬空。
 *
 * @author   ChatRoom Laravel
 *
 * @version  1.0.0
 */

namespace App\Console\Commands;

use App\Models\PositionDutyLog;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

class CloseStaleDutyLogs extends Command
{
    /**
     * Artisan 指令名称
     */
    protected $signature = 'duty:close-stale-logs';

    /**
     * 指令描述（在 artisan list 中显示）
     */
    protected $description = '自动关闭 15 分钟内无心跳的开放职务日志（解决掉线不结算问题）';

    /**
     * 指令入口：将长时间无心跳刷新的开放日志判定为掉线，写入 logout_at 完成结算。
     *
     * 判定标准：updated_at 超过 15 分钟（心跳间隔约 30 秒，5 分钟自动存点最长 5 分钟，
     * 留足 10 分钟容差，总计 15 分钟无刷新即认为掉线）
     */
    public function handle(): int
    {
        // 15 分钟无心跳 = 掉线判定阈值
        $threshold = now()->subMinutes(15);

        // 批量关闭符合条件的开放日志，保留现有 duration_seconds
        $affected = PositionDutyLog::query()
            ->whereNull('logout_at')
            ->where('updated_at', '<=', $threshold)
            ->update([
                'logout_at' => DB::raw('NOW()'),
                // 补算最终在线时长，避免日榜 SUM 使用过时的旧值
                'duration_seconds' => DB::raw('GREATEST(0, TIMESTAMPDIFF(SECOND, login_at, NOW()))'),
            ]);

        if ($affected > 0) {
            $this->info("共关闭 {$affected} 条掉线职务日志。");
        } else {
            $this->info('无需处理，无掉线日志。');
        }

        return Command::SUCCESS;
    }
}
