<?php

declare(strict_types=1);

namespace Kylin\User\Commands;

use Illuminate\Console\Command;
use Kylin\User\Models\User;

/**
 * 用户数据清理命令
 *
 * 依据《个人信息保护法》第四十七条：
 * 处理目的已实现或保存期限届满时应删除个人信息。
 *
 * 清理策略：
 *  - 软删除超过 `data_retention_days` 天的用户数据
 *  - 已锁定超过 `data_retention_days` 天且未活跃的用户
 *  - 用户注销后保留期内保护，期满后清理
 *
 * 使用方式：
 *   php artisan user:clean --dry-run   # 预览将清理的数据
 *   php artisan user:clean              # 执行清理
 *   php artisan user:clean --days=90    # 自定义保留天数
 */
class CleanUserDataCommand extends Command
{
    protected $signature = 'user:clean
                            {--dry-run : 预览模式，不实际删除}
                            {--days= : 数据保留天数，默认使用配置值}
                            {--force : 强制清理（包括未到期数据）}';

    protected $description = '清理超期用户数据，符合《个人信息保护法》合规要求';

    public function handle(): int
    {
        $retentionDays = (int) ($this->option('days') ?? config('kylin-user.privacy.data_retention_days', 365));
        $isDryRun = $this->option('dry-run');

        // 防止误删：最小保留期 90 天
        if ($retentionDays < 90 && ! $this->option('force')) {
            $this->error('数据保留期不能少于 90 天。使用 --force 强制清理。');
            return self::FAILURE;
        }

        $cutoffDate = now()->subDays($retentionDays);

        $this->info("数据保留期: {$retentionDays} 天");
        $this->info("截止日期: {$cutoffDate->toDateString()}");
        $this->info('');

        if ($isDryRun) {
            $this->warn('=== 预览模式：不会实际删除数据 ===');
            $this->newLine();
        }

        // 1. 清理已软删除的用户
        $trashedCount = $this->cleanTrashedUsers($cutoffDate, $isDryRun);

        // 2. 清理已锁定且长期未活跃的用户
        $lockedCount = $this->cleanLockedInactiveUsers($cutoffDate, $isDryRun);

        $totalCount = $trashedCount + $lockedCount;

        $this->newLine();
        if ($isDryRun) {
            $this->info("预览完成：共 {$totalCount} 条数据待清理（软删除用户: {$trashedCount}，锁定用户: {$lockedCount}）");
            $this->info('使用 php artisan user:clean 执行实际清理');
        } else {
            $this->info("清理完成：共清理 {$totalCount} 条数据（软删除用户: {$trashedCount}，锁定用户: {$lockedCount}）");
        }

        return self::SUCCESS;
    }

    /**
     * 清理已软删除的超期用户数据
     */
    private function cleanTrashedUsers(\DateTimeInterface $cutoffDate, bool $isDryRun): int
    {
        $query = User::onlyTrashed()
            ->where('deleted_at', '<', $cutoffDate);

        $count = $query->count();

        if ($count > 0) {
            $this->line("软删除超期用户: {$count} 条");

            if (! $isDryRun) {
                // 使用 forceDelete() 彻底删除，符合《个人信息保护法》要求
                $query->chunkById(100, function ($users) {
                    foreach ($users as $user) {
                        // 删除关联的用户资料
                        if ($user->profile) {
                            $user->profile->delete();
                        }
                        $user->forceDelete();
                    }
                });
            }
        }

        return $count;
    }

    /**
     * 清理已锁定且长期未活跃的用户
     */
    private function cleanLockedInactiveUsers(\DateTimeInterface $cutoffDate, bool $isDryRun): int
    {
        $query = User::query()
            ->where('status', 2) // 已锁定
            ->where(function ($q) use ($cutoffDate) {
                $q->whereNull('login_at')
                    ->orWhere('login_at', '<', $cutoffDate);
            });

        $count = $query->count();

        if ($count > 0) {
            $this->line("锁定未活跃用户: {$count} 条");

            if (! $isDryRun) {
                $query->chunkById(100, function ($users) {
                    foreach ($users as $user) {
                        if ($user->profile) {
                            $user->profile->delete();
                        }
                        $user->forceDelete();
                    }
                });
            }
        }

        return $count;
    }
}