<?php

namespace Kylin\Activity;

use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Console\ConfirmableTrait;
use Illuminate\Database\Eloquent\Builder;

/**
 * 清理活动日志命令
 *
 * Artisan 命令：php artisan activitylog:clean
 * 删除超过指定天数的活动日志记录。
 *
 * 依据《网络安全法》第二十一条，日志保留 >= 180 天后方可清理。
 * 使用 forceDelete() 绕过防篡改保护，确保合规清理。
 *
 * 参数：
 *  - log：指定要清理的日志名称（可选）
 *  - --days：删除超过指定天数的记录（默认从配置读取，最小 180 天）
 *  - --force：生产环境强制执行
 */
class CleanActivitylogCommand extends Command
{
    use ConfirmableTrait;

    /** 命令签名 */
    protected $signature = 'activitylog:clean
                            {log? : (optional) 要清理的日志名称}
                            {--days= : (optional) 删除超过此天数的记录}
                            {--force : (optional) 生产环境强制执行}';

    /** 命令描述 */
    protected $description = '清理活动日志中的旧记录';

    /**
     * 执行清理命令
     *
     * @return int  0 成功，1 用户取消
     */
    public function handle()
    {
        if (! $this->confirmToProceed()) {
            return 1;
        }

        $this->comment('正在清理活动日志...');

        $log = $this->argument('log');

        $maxAgeInDays = $this->option('days') ?? config('kylin-activity.delete_records_older_than_days', 365);

        // 依据《网络安全法》第二十一条，最低保留 180 天
        if ($maxAgeInDays < 180) {
            $this->warn('依据《网络安全法》第二十一条，日志保留期最少为 180 天。已自动调整为 180 天。');
            $maxAgeInDays = 180;
        }

        if (filter_var($maxAgeInDays, FILTER_VALIDATE_INT) === false) {
            $this->error('The days option must be an integer.');

            return 1;
        }

        $maxAgeInDays = (int) $maxAgeInDays;

        $cutOffDate = Carbon::now()->subDays($maxAgeInDays)->format('Y-m-d H:i:s');

        $activity = ActivitylogServiceProvider::getActivityModelInstance();

        // 使用 forceDelete() 绕过防篡改保护，仅允许此处清理过期日志
        $records = $activity::query()
            ->where('created_at', '<', $cutOffDate)
            ->when($log !== null, function (Builder $query) use ($log) {
                $query->inLog($log);
            })
            ->get();

        $amountDeleted = 0;
        foreach ($records as $record) {
            $record->forceDelete();
            $amountDeleted++;
        }

        $this->info("Deleted {$amountDeleted} record(s) from the activity log.");

        $this->comment('All done!');
    }
}
