<?php

namespace App\Console\Commands;

use App\Models\Customer;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;

/**
 * Registrations nobody ever confirmed, removed.
 *
 * An abandoned attempt used to stay in `users` for ever, and it holds the
 * address hostage while it does: the unique index means the same person cannot
 * register again with the address they meant. "Abmelden und neu registrieren"
 * was therefore advice that could not work — signing out frees nothing.
 *
 * Five days, because that is long enough for somebody who registered on a
 * Friday, found the mail in a spam folder on Monday, and clicked it — and short
 * enough that a typo does not block the correct address for a month.
 *
 * What it will NOT touch, and this is the important half:
 *
 *  - a confirmed account, whatever else is true of it;
 *  - an account with a customer record behind it. A paid checkout creates the
 *    login through the webhook, and such a user can sit unconfirmed while
 *    already having a contract. Deleting that is data loss, not housekeeping.
 */
class PruneUnverifiedAccounts extends Command
{
    /** How long an unconfirmed registration is kept. */
    public const AFTER_DAYS = 5;

    protected $signature = 'clupilot:prune-unverified {--dry-run : Only say what would go}';

    protected $description = 'Delete registrations that were never confirmed';

    public function handle(): int
    {
        $stale = User::query()
            ->whereNull('email_verified_at')
            ->where('created_at', '<', now()->subDays(self::AFTER_DAYS))
            // Not a join: the two tables are linked by user_id OR by address
            // (see Customer::emailTaken — a row can predate or outlive the
            // other), and either one means somebody is a customer.
            ->whereNotExists(fn ($q) => $q->selectRaw('1')->from('customers')
                ->whereColumn('customers.user_id', 'users.id'))
            ->whereNotExists(fn ($q) => $q->selectRaw('1')->from('customers')
                ->whereColumn('customers.email', 'users.email'))
            ->get();

        if ($stale->isEmpty()) {
            $this->info('Nothing to remove.');

            return self::SUCCESS;
        }

        if ($this->option('dry-run')) {
            foreach ($stale as $user) {
                $this->line('would remove: '.$user->email.' (registered '.$user->created_at->toDateString().')');
            }

            return self::SUCCESS;
        }

        foreach ($stale as $user) {
            // Logged individually rather than as a count: an address that
            // disappears is the kind of thing somebody asks about later, and a
            // number in a log answers nothing.
            Log::info('Removing an unconfirmed registration', [
                'email' => $user->email,
                'registered_at' => $user->created_at?->toIso8601String(),
            ]);

            $user->delete();
        }

        $this->info($stale->count().' unconfirmed registration(s) removed.');

        return self::SUCCESS;
    }
}
